Skip to content

Proxy web applications using nginx

Delvin Defoe edited this page Apr 15, 2016 · 6 revisions

Hosting multiple web apps with nginx

According to a blog on the nginx website, nginx is a high-performance load balancer, cache, and web server, which has found growing usage. With nginx, we can use a server with a single public IP address to host multiple web applications, each with its own port number and/or private IP address, e.g., http://my.domain.com, http://my.other.domain.com, http://localhost:5000, http://localhost:9999.

This is made possible by the fact that Internet browsers send domain names inside HTTP requests. When the request is received by the nginx server, it parses the requested domain name and URL, then routes the HTTP request to the hosted web server of the respective web app. That app processes the request and responds as if it were accessed directly.

Note that you do not want to parse HTTP requests yourself. There is a plethora of tools and technologies that can do that for you, including nginx. nginx can proxy multiple web applications using a single VM or physical server.

Installing nginx

Mac OSX installation of nginx

The simplest process for installing nginx on a Mac uses Homebrew. From the console, verify that Homebrew is installed on your machine.

brew --version

If Homebrew is not installed (you did not gee a version number), install it by following the instructions posted on the Homebrew site. Since Homebrew can self-diagnose, verify that everything is is fine and works how it should. If there are issues, Homebrew will report back to you. Fix any reported issues before moving on.

brew doctor

Ensure that you have the latest version of Homebrew and that it has the most up-to-date list of formulae available from the main repository.

brew update

You should expect to see "Already up-todate". Here are a few other Homebrew commands that may interest you. Now you are ready to install nginx by simply following this command.

brew install nginx

Verify installation by checking what version got installed -- nginx -v. You should see 1.8.0 or higher if installation was successful.

When installation in complete, you can enter the command below in your terminal to start nginx.

sudo nginx

Ubuntu 14.04 installation of nginx

Be sure that you have a non-root user account with sudo access configured on your system. Login with that account and update you list of packages to ensure that you are accessing the most up-to-date information by issuing the command below from a terminal.

sudo apt-get update

Installation of nginx is as easy as following this instruction.

sudo apt-get install nginx

Running nginx -v will verify whether your installation was successful by displaying version number 1.4.6 or higher.

When nginx is successfully installed, it will start automatically.

Windows installation of nginx

In your web browser, navigate to http://nginx.org/en/download.html and click on the version of the nginx installer that you wish to use to complete your installation. You should select the Mainline version or the Stable version.

Launch the Command Prompt from the Run Window. One of the quickest ways to do so is to use the Run Window (press Win+R on your keyboard to open it) shortcut. Now type cmd or cmd.exe and press Enter. Thee are at least 7 Ways to Launch The Command Prompt in Windows.

Unpack the nginx installation file you downloaded, then go to the nginx created directory and then run nginx. Here is an example for the drive C: root directory:

cd c:\
unzip nginx-1.9.14.zip
cd nginx-1.9.14

Note: nginx/Windows runs as a standard console application (not a service), and it can be managed using the following commands:

nginx -s stop	// fast shutdown
nginx -s quit	// graceful shutdown
nginx -s reload	// changing configuration, starting new worker processes with a new configuration, graceful shutdown of old worker processes
nginx -s reopen	// re-opening log files

Upon successful installation of nginx, you can start it by entering the command below in your command prompt window:

start nginx

Proxying through an nginx server

According to Wikipedia, a proxy server is a server (computer system or application) that acts as an intermediary for requests from clients seeking resources from other servers. Suppose that your web browser is making requests for resources from an AngularJS front-end application that is hosted at address http://my.domain.com:5000. Suppose that the backend API associated with this front-end application is hosted at address http://my.domain.com:5001. Note the different port numbers.

Instead of entering http://my.domain.com:5000 in your browser to access the front-end OR http://my.domain.com:5001 to access the backend API, it might be more convenient to use the following addresses:

  • http://my.domain.com to access the front-end application
  • http://my.domain.com/api to access the backend API

The good news is this can be accomplished by proxying through an nginx server. All that's need is to make a few configuration changes, as described below.

nginx configuration file

On Mac OSX, the configuration file is located at /usr/local/etc/nginx/nginx.conf.

On Ubuntu, the configuration file is located at /etc/nginx/sites-available/default.

On Windows, the configuration file is located at \path\to\nginx\conf\nginx.conf.

With admin or sudo privilege, save a copy of your original config file (in case you make a mistake and wish to revert back to it) with a .original extension. Now you can make changes with your favorite editor to the config file (not the copy). You need to open this file with admin or sudo privilege, so you can save your changes.

Stopping and restarting nginx

In your nginx config file, find a server block. It should look something like this:

server {
    listen       80;
    ...
    location / {
       ...
    }
    ...
}

You can choose to change the port number from 80 to something else, if you choose, but the default http port number, 80, is perfectly fine. Reaffirm that your nginx installation was error-free to ensure that you are at a solid starting point.

Mac

sudo nginx -s stop && sudo nginx

Ubuntu

sudo service nginx restart

Windows

nginx -s reload

Browser test

Open your web browser and point it to http://localhost. If you changed the default port number from 80 to another port number, say 9000, then you would point your browser to http://localhost:9000 instead. You should see the default nginx index page displayed in your browser.

Configuring / and /api

Suppose we want to configure nginx to route requests for / to http://localhost:5000 and requests for /api to http://localhost:5001.

                  +--- host --------> AngularJS on localhost:5000
client--> nginx --|
                  +--- host/api ---> node.js on localhost:5001             

To route these requests, we need to edit the config file. Find the serverblock noted above and make these changes.

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }
    location /api {
        proxy_pass http://127.0.0.1:5001;
    }
}

You will notice that We have not changed the port number on which the nginx server listens, that is, on port number 80. We have, however, added two location blocks. Each location block tells nginx what to do when it receives requests. Inside the location blocks we use proxy_pass to tell nginx to forward requests to the server listening on the indicated port number. In our case, location / instructs nginx to forward requests to http://localhost:5000--the AngularJS front-end application and location /api instructs nginx to forward requests to http://localhost:5001--the backend API application server.

After making these changes, save the config file, start both the AngularJS and backend API applications, and restart nginx.

Pointing your browser to http://localhost should now display your AngularJS application. In like manner, pointing your browser to http://localhost/api should now display your backend API application, or maybe not. You probably got a 404 error.

Rewriting Requests

The reason that you got the 404 error is that your backend application is is expecting requests from /, but instead got requests from /api.

To resolve this issue, we need to rewrite the URL so that it matches the URL that the backend server is expecting. The config file needs to be update accordingly.

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }
    location /api {
        rewrite ^/api(.*) $1 break;
        proxy_pass http://127.0.0.1:5001;
    }
}

Note the change in the location /api block. This rewrite command uses a simple regular expression that transforms routes like /apiSOMETHING_ELSE to /SOMETHING_ELSE in the incoming HTTP requests.

Saving the config file and restarting nginx should cause everything to work as expected.

Setting Up SSL

In a live environment, you may want to configure SSL to protect sensitive information. There are several Certificate Authorities (CAs) that you can use to issue you a certificate. Or you can choose to create a self-signed certificate. Note that your browser will warn you that the self-signed certificate is not trusted. It is OK to use self-signed certificates for local testing. This is exactly what we will do.

Once you have the certificate and a private key stored on your machine, you can setup SSL in nginx. You need to modify our previous server block to the following:

server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate      /path/to/ssl/cert.pem;
    ssl_certificate_key  /path/to/ssl/key.pem;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    location / {
        proxy_pass http://127.0.0.1:5000;
    }
    location /api {
        rewrite ^/api(.*) $1 break;
        proxy_pass http://127.0.0.1:5001;
    }
}

Now if you access https://localhost your SSL setup should work. Be sure you are accessing the certificate file and private key correctly. You will need to know where these are stored so you can access them correctly.

Ensuring that all paths are secure

The last thing that we need to do is ensure that all requests are protected. To do so, we need to rewrite all http requests to https while maintaining sub-domains. This can be done by configuring another server block like this:

server {
   listen         80 default_server;
   listen         [::]:80 default_server;
   server_name    _;
   return         301 https://$host$request_uri;
}

This will forward all requests that are made on port number 80 to port number 443. That is to say that all http requests are rewritten to be https requests.

Conclusion

In this blog, we provided instructions for installing and running nginx and using it to proxy multiple web applications. We also described hot to configure SSL in nginx. Using nginx in front of your application servers can improve their security and make them less susceptible to attacks.

Resources