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.
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
.
Follow these steps to set Nginx as a reverse proxy:
$ sudo apt-get update $ sudo apt-get install nginx
/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; } }
sites-enabled
:$ sudo ln -s /etc/nginx/sites-available/reverse_proxy /etc/nginx/sites-enabled/reverse_proxy
sites-enabled
:$ sudo rm /etc/nginx/sites-enabled/default
8080
. This will leave port 80
to be used by Nginx:$ sudo nano /etc/apache2/ports.conf listen 127.0.0.1:8080
NameVirtualHost
, if you are using it:NameVirtualHost 127.0.0.1:8080
8080
:$ sudo nano /etc/apache2/sites-available/example.com <VirtualHost 127.0.0.1:8080> ServerName example.com ServerAdmin [email protected] DocumentRoot /var/www/example.com/public_html </VirtualHost>
$ sudo service apache2 restart
$ sudo service nginx restart
$ sudo netstat -pltn
example.com
.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.
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 updatedHAProxy 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.