Skip to content

Instantly share code, notes, and snippets.

@tranghaviet
Forked from soheilhy/nginxproxy.md
Created October 17, 2021 15:55

Revisions

  1. @soheilhy soheilhy revised this gist May 18, 2014. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions nginxproxy.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,5 @@
    # Virtual Hosts on nginx (CSC309)

    [TOC]

    When hosting our web applications, we often have one public IP
    address (_i.e.,_ an IP address visible to the outside world)
    using which we want to host multiple web apps. For example, one
  2. @soheilhy soheilhy revised this gist May 18, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions nginxproxy.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    # Virtual Hosts on nginx (CSC309)

    [TOC]

    When hosting our web applications, we often have one public IP
    address (_i.e.,_ an IP address visible to the outside world)
    using which we want to host multiple web apps. For example, one
  3. @soheilhy soheilhy revised this gist May 18, 2014. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions nginxproxy.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,5 @@
    # Virtual Hosts on nginx (CSC309)
    :with_toc_data

    [TOC]
    When hosting our web applications, we often have one public IP
    address (_i.e.,_ an IP address visible to the outside world)
    using which we want to host multiple web apps. For example, one
  4. @soheilhy soheilhy revised this gist May 18, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions nginxproxy.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    # Virtual Hosts on nginx (CSC309)
    :with_toc_data

    When hosting our web applications, we often have one public IP
    address (_i.e.,_ an IP address visible to the outside world)
  5. @soheilhy soheilhy created this gist May 18, 2014.
    272 changes: 272 additions & 0 deletions nginxproxy.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,272 @@
    # Virtual Hosts on nginx (CSC309)

    When hosting our web applications, we often have one public IP
    address (_i.e.,_ an IP address visible to the outside world)
    using which we want to host multiple web apps. For example, one
    may wants to host three different web apps respectively for
    `example1.com`, `example2.com`, and `example1.com/images` on
    the same machine using a single IP address.

    **How can we do that?** Well, the good news is Internet browsers
    send the domain name inside HTTP requests and all we need to do
    is to parse the requested domain name and URL and then route the
    HTTP request to the actual web server.

    **Oh, do I really need to parse HTTP requests?** You can if you
    really want to, but there are lots of tools and technologies that
    readily do this for you. In this tutorial, we walk you through
    how you can use nginx to _proxy_ multiple web applications.

    ## Install nginx

    ### CDF @UofT
    We have prepared pre-copmiled binaries for your.
    You need to download [nginx.tar.gz](http://www.cs.toronto.edu/~soheil/csc309/nginx.tar.gz)
    and uncompress it:
    ```sh
    $ wget http://www.cs.toronto.edu/~soheil/csc309/nginx.tar.gz && tar -xvzf nginx.tar.gz
    ```

    - It creates an nginx directory for you. The config file
    is in `nginx/conf/nginx.conf`.
    - We have provided a script named `nginx` in the directory.
    To run `nginx`, go to the `nginx` directory (`cd nginx`) and
    run `./nginx ...`.

    ### Ubuntu
    Install `nginx` using `apt-get`:
    ```sh
    $ sudo apt-get install nginx
    ```
    **Notes:**

    - The part of the `nginx`'s config file we need resides in `/etc/nginx/sites-enabled/default`.
    - To edit the config file or run `nginx`, you need to use `sudo`.

    ### Mac OS
    Install [`homebrew`](http://brew.sh), and then install `nginx` using `brew`:
    ```sh
    $ brew install nginx
    ```
    **Notes:**

    - `nginx`'s config file is in `/usr/local/etc/nginx/nginx.conf`.
    - To edit the config file or run `nginx`, you need to use `sudo`:
    `sudo nano /usr/local/etc/nginx/nginx.conf` and
    `sudo nginx ...`

    ## Configuration

    ### Step 1 -- Booting Servers for Virtual Hosts
    Write three different node applications running on different ports
    (say 8080, 8181, 8282) on your machine.

    ### Step 2 -- Configure nginx's Port
    To do so, you need to edit your `nginx` config file.

    In the config file, find the `server` section:
    ```
    server {
    listen 80;
    ...
    location / {
    ...
    }
    ...
    }
    ```

    **If you're using CDF**, make sure you change `80` to a vacant port number
    (ask for one from your instructor). If not, you can keep using `80` or
    change the port if you will.

    **Test nginx**

    1. Run `./nginx` on CDF, or run `sudo nginx` on your local machine.
    2. Open the browser and log on to `localhost:$PORT` (replace `$PORT` with
    the port number you configured for `nginx`).

    ### Step 3 -- Configure /
    Let say we want to configure `nginx` to route requests for
    `/`, `/blog`, and `/mail`, respectively onto
    `localhost:8080`, `localhost:8181`, and `localhost:8282`.

    ```
    +--- host --------> node.js on localhost:8080
    |
    users --> nginx --|--- host/blog ---> node.js on localhost:8181
    |
    +--- host/mail ---> node.js on localhost:8282
    ```

    To route `/`, you need to edit your `nginx` config file.

    In the config file, find the `server` section:
    ```
    server {
    listen 80;
    ...
    location / {
    ...
    }
    ...
    }
    ```

    This section is simply telling `nginx` how it should serve HTTP requests.

    Now, change the location section to this snippet:

    ```
    server {
    listen ...;
    ...
    location / {
    proxy_pass http://127.0.0.1:8080;
    }
    ...
    }
    ```

    `proxy_pass` simply tells `nginx` to forward requests to `/` to the
    server listening on `http://127.0.0.1:8080`.

    ### Step 4 -- Reload nginx's Configuration

    To reload `nginx`'s configuration run:
    `nginx -s reload` on your machine.

    Referesh your browser. _Do you see the output from your `node.js` application?_
    If yes, you are all set. If no, there is a problem with your config.

    ### Step 5 -- Add /blog and /mail

    To redirect `/mail` and `/blog`, you simply need to add new entries
    the location section in the config file:

    ```
    server {
    listen ...;
    ...
    location / {
    proxy_pass http://127.0.0.1:8080;
    }
    location /blog {
    proxy_pass http://127.0.0.1:8181;
    }
    location /mail {
    proxy_pass http://127.0.0.1:8282;
    }
    ...
    }
    ```

    ### Step 6 -- Reload Your nginx Configuration
    Run `nginx -s reload` on your machine.

    Log onto `localhost:$PORT/blog` in your browser.
    _Do you see the output from your second `node.js` application?_

    Then log onto `localhost:$PORT/mail`.
    _Do you see the output from your third `node.js` application?_

    If yes & yes, you are all set. If no, there is a problem with your config.

    ### Step 7 -- Rewriting Requests
    Now as you might have noticed in Step 6, nginx sends the same
    HTTP request to your `node.js` web apps which results into a 404 error.
    Why? Because, your `node.js` web application serves requests from `/`
    not from `/blog` and `/mail`. But, `nginx` is sending requests to `/blog` and
    `/mail`.

    To fix this issue, we need rewrite the URL so that it matches the URL
    you can serve on your `node.js` applications.

    To correctly rewrite URLs change your config file to match the following snippet:

    ```
    server {
    listen ...;
    ...
    location / {
    proxy_pass http://127.0.0.1:8080;
    }
    location /blog {
    rewrite ^/blog(.*) /$1 break;
    proxy_pass http://127.0.0.1:8181;
    }
    location /mail {
    rewrite ^/mail(.*) /$1 break;
    proxy_pass http://127.0.0.1:8282;
    }
    ...
    }
    ```

    This rewrite commands are simple regular expressions that transform
    strings like `/blogWHAT_EVER` and `/mailWHAT_EVER` to `/WHAT_EVER`
    in the HTTP requests.

    ### Step 8 -- Reload and Test.
    All set?

    ### Exercise 1
    Configure your nginx to redirect URLs from `/google` to `http://www.google.com`


    ### Step 9 (optional) -- Redirecting Based on Host Name
    Let say you want to host `example1.com`, `example2.com`, and `example3.com`
    on your machine, respectively to `localhost:8080`, `localhost:8181`, and
    `localhost:8282`.

    **Note:** Since you don't have access to a DNS server, you should
    add domain name entries to your `/etc/hosts` (you can't do this on CDF machines):

    ```
    ...
    127.0.0.1 example1.com example2.com example3.com
    ...
    ```

    To proxy `eaxmple1.com` we can't use the location part of the default server.
    Instead we need to add another server section with a `server_name` set
    to our virtual host (e.g., `example1.com`, ...), and then a simple location
    section that tells `nginx` how to proxy the requests:

    ```
    server {
    listen 80;
    server_name example1.com;
    location / {
    proxy_pass http://127.0.0.1:8080;
    }
    }
    server {
    listen 80;
    server_name example2.com;
    location / {
    proxy_pass http://127.0.0.1:8181;
    }
    }
    server {
    listen 80;
    server_name example3.com;
    location / {
    proxy_pass http://127.0.0.1:8282;
    }
    }
    ```

    Simple, ha?!