Setting Nginx as a reverse proxy
Apache and Nginx are two popular open source web servers. Both are very powerful, but at the same time have their own disadvantages as well. Apache is not good at handling high load environments with multiple concurrent requests and Nginx does not have inbuilt support for dynamic content processing. Many administrators overcome these problems by using both Apache and Nginx together. Nginx handles all incoming requests and only passes requests for dynamic content to Apache. Additionally, Nginx can provide a catching option which enables the server to respond to a request with results from a similar previous request. This helps to reduce the overall response time and minimize the load sent to Apache.
In this recipe, we will learn how to set up a web server configured with a reverse proxy. We will use Nginx as a reverse proxy, which will serve all static content and pass the requests for dynamic content to Apache.
Getting ready
You will need access to a root account or an account with sudo
privileges.
I assume that Apache is installed and running with a virtual host, example.com
.
How to do it…
Follow these steps to set Nginx as a reverse proxy:
- Install Nginx with the following command:
$ sudo apt-get update $ sudo apt-get install nginx
- Create a new site configuration under
/etc/nginx/sites-available
and add the following content to it:$ sudo nano /etc/nginx/sites-available/reverse_proxy server { listen 80; root /var/www/example.com; index index.php index.html index.htm; server_name example.com; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $host; proxy_pass http://127.0.0.1:8080; } location ~* \.(js|css|jpg|jpeg|png|svg|html|htm)$ { expires 30d; } location ~ /\.ht { deny all; } }
- Enable this new configuration by creating a symbolic link under
sites-enabled
:$ sudo ln -s /etc/nginx/sites-available/reverse_proxy \ /etc/nginx/sites-enabled/reverse_proxy
- Optionally, disable the default site by removing the symbolic link from
sites-enabled
:$ sudo rm /etc/nginx/sites-enabled/default
- Next, we need to change the Apache settings to listen on port
8080
. This will leave port80
to be used by Nginx:$ sudo nano /etc/apache2/ports.conf listen 127.0.0.1:8080
- Also change
NameVirtualHost
, if you are using it:NameVirtualHost 127.0.0.1:8080
- Change the virtual hosts settings to listen on port
8080
:$ sudo nano /etc/apache2/sites-available/example.com <VirtualHost 127.0.0.1:8080> ServerName example.com ServerAdmin webmaster@example.com DocumentRoot /var/www/example.com/public_html </VirtualHost>
- Save the changes and restart Apache for the changes to take effect:
$ sudo service apache2 restart
- Now, restart Nginx:
$ sudo service nginx restart
- Check for open ports with the following command:
$ sudo netstat -pltn
- Open your browser and point it to the IP address of your server. It should load the page configured under the Apache virtual host,
example.com
.
How it works…
With the proxy_pass
parameter, we have simply asked Nginx to pass all requests for PHP scripts to Apache on 127.0.0.1
on port 8080
. Then, we set Apache to listen on the loopback IP and port 8080
, which will receive requests forwarded by Nginx and process them with an internal PHP processor. All non-PHP content will still be served by Nginx from the /var/www
directory. The try_files $uri $uri/ /index.php;
option sets Nginx to search for the file with a specified name and then look for the folder; lastly, if both file and folder are not found, send the request to index.php
, which will then be processed by Apache.
Other options used with proxy pass ensures that Apache and PHP scripts receive the actual hostname and IP of the client and not of the Nginx server. You can use an additional module named libapache2-mod-rpaf
on Apache. This module provides an option to set a proxy IP address and rename the parameters sent by the proxy server. You can install the module with the following command:
$ sudo apt-get install libapache2-mod-rpaf
The configuration file for this module is available at /etc/apache2/mods-available/rpaf.conf
.
You can find various other proxy options and their respective explanations in the Nginx documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html
Finally, with Nginx set as a frontend, Apache will not have to interact directly with HTTP clients. You may want to disable some of the Apache modules that will not be used in this setup:
$ sudo a2dismod deflate cgi negotiation autoindex
As always, do not forget to reload Apache after any changes.
There's more…
Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m; proxy_cache_key "$scheme$request_method$host$request_uri$args"; server { ## add other settings heres location / { proxy_pass 127.0.0.1:8080; proxy_cache backend-cache; proxy_cache_bypass $http_cache_control; add_header X-Proxy-Cache $upstream_cache_status; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; } }
You may need to create the proxy path directory /data/nginx/cache
and set the appropriate file permissions. Set the directory ownership to www-data
and restrict permissions to 700
. You can use any location for cache data and not necessarily /data/nginx/cache
.
This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:
proxy_cache_lock on
: Queues additional requests while the cache is being updatedproxy_cache_use_stale updating
: Uses stale data while the cache is being updated
HAProxy and Varnish
HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.
See also
- Nginx admin guide on reverse proxies at https://www.nginx.com/resources/admin-guide/reverse-proxy/
- Understanding Nginx proxying, load balancing, and caching at https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching
- Nginx proxy module documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html