Knowledge Base - How to Configure Nginx as a Reverse Proxy in Ubuntu 14.04

In simple words Proxy is nothing but an intermediate entity or  service/system/application/computer through which a user makes a request for resource/file/service and gets its response.

 

A Proxy can be classified into three different types.

 

  • A Simple Proxy
  • A Forward Proxy
  • A Reverse Proxy

 

 

A Proxy Server that serves the user requests and responses without any kind of modification in between is called a Simple Proxy. This type of Proxy is often referred to as Gateways or a tunneling Proxy.

A Forward proxy is something that is generally used to filter outgoing connections to anywhere in the internet. This can also be used for anonymous access of the internet.

A Reverse Proxy(the topic that we will be discussing here in this article), can be viewed as a broker sitting in front to serve user requests to the backend servers.

 

Reverse proxies are good for the below things.

 

  • Load Balancing inbound requests
  • Firewalling your application
  • Obfuscating Servers
  • Caching
  • SSL Offloading and Acceleration
  • Authentication & Single Sign-on

 

 

This tutorial will walk you through the steps required to Configure, Nginx web server as a front end Reverse Proxy. This will then proxy user requests to backend nodes.

 

 

 

 

The first step is to install Nginx on your server. This can be done in Ubuntu 14.04 pretty easily as shown below.

 

sudo apt-get install nginx

Lets first remove the default nginx configuration file as shown below.

 

 

cd /etc/nginx/

rm sites-enabled/default

Now the next step is to create a new configuration file that contains our website specific configuration. This can be done by creating it as shown below.

 

cd /etc/nginx/sites-available

touch mydomain.com

Now lets populate our mydomain.com file with our required Proxy configuration as shown below (the file name does not matter, mydomain.com is just an example, assuming mydomain.com as the domain that the configuration is for. You can also have anything.com, example.com etc.)

 

 

server {

listen 80;

server_name mydomain.com;

access_log /var/log/nginx/mydomain.com

location / {

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header HOST $http_host;

proxy_pass http://10.1.132.43:80;

proxy_redirect off;

}

}

Lets now enable the configuration we just created for mydomain.com in nginx. This is done by creating a simple sym link to the config file we created as shown below.

 

 

cd /etc/nginx

ln -s sites-available/ghost sites-enabled/ghost

Lets now restart nginx, to verify the proxy configuration we just made.

 

service nginx restart

You can verify the proxy configuration by putting mydomain.com in your web browser and verify if its showing the content hosted by 10.1.132.43:80 .

 

Please note the fact that you need to have DNS configured properly to make this work. This is because nginx is looking for the server name you type in the browser. If the request hits the nginx server with the name mydomain.com, then it will show you the page at 10.1.132.43:80 .

 

If you do not have DNS configured to point to the nginx server we configured, you can easily test this by simply adding the entry like mydomain.com —-> our-nginx-server-ip-address.

 

In the configuration shown above for mydomain.com, we have only one single backend server. Lets see a configuration for having multiple backend servers. This involves adding an upstream block inside nginx configuration as shown below.

 

upstream will basically contain a pool of backend servers.

 

upstream backend_app {

server 10.1.131.30:80;

server 10.1.131.31:80;

server 10.1.131.32:80;

}

server {

listen 80;

server_name mydomain.com;

location / {

proxy_pass http://backend_app;

}

}

As you can clearly see in the above configuration, you can give any name to your upstream block (we have given the example name of “backend_app”), and then simply call that in proxy_pass parameter.

 

The location argument in the above configuration specifies the request path for which the backend pool will be used. You can modify that according to your requirement. Say for example, you only need to use that backend pool of servers for a particular url like /main/application then your configuration will look as below.

 

server_name mydomain.com;

location /main/application {

proxy_pass http://backend_app;

}

}

In this case, nginx will check the URL path requested by the client, and will use the backend only if the location in the path is /main/application.

 

Another thing to note about the upstream block is that you can specify the kind of algorithm that should be used while sending requests to these backend servers. The algorithm that you select will depend upon your use case. The default one is round-robin.

 

Other algorithms that you can use for upstream  is mentioned below.

 

round_robin: Requests is sent sequentially to backend nodes specified in upstream block

 

least_conn: This can be used, if the request needs to be sent to a backend node with least number of connections.

 

ip_hash: This algorithm is very useful, if your application is session aware. In other words, nginx will calculate a hash based on the first few numbers of the source ip address, and will send requests originated from there to the same backend server.

 

 

upstream backend_app {

least_conn;

server 10.1.131.30:80;

server 10.1.131.31:80;

server 10.1.131.32:80;

}

You can use the ip_hash algorithm also in the same way as above. ip_hash can be used to achieve sticky session.

 

If you want to send more traffic to only one particular backend server from the upstream pool, in that case you can use weighted load balancing as shown below.

 

upstream backend_app {

server 10.1.131.30:80;

server 10.1.131.31:80 weight=3;

server 10.1.131.32:80;

}

In the above shown example, the backend server 10.1.131.31 will recieve more traffic compared to other two servers. To be accurate, 10.1.131.31 will recive around 3 times the traffic that is being sent to other two servers.

 

The default weight for all servers will be 1.

 

 

If you want nginx to send the exact source address of the request(ie: the request originated source..the user’s source Ip address), to the backend servers, then you can set the X-forwarded-for as shown below.

 

 

server {

listen 80;

server_name mydomain.com;

proxy_set_header X-Forwarded-For $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

location / {

proxy_pass http://backend_app;

}

Without setting the above, the backend servers will always feel the request actually originated from the nginx proxy server.