Setup Nginx as Reverse Proxy and Cache Server for Apache

Nginx is used as not only a web server but also as a reverse proxy with the ability to cache content.

There are two types of proxy servers, forward and reverse. In this post, I will focus on setting up Nginx as a reverse proxy with caching content from back-end servers.

What is a Reverse Proxy?

A reverse proxy is a server that sits in front of your website or web services and forwards incoming client requests to the back-end and on successful retrieval of the information, sends the result back to the client applications or browsers.

In its role as an intermediary, it provides the ability to enhance the security, performance and reliability of the servers it communicates with. Let’s go quickly over the above mentioned benefits of a reverse proxy.

Reverse Proxy and Caching Flow Nginx and Others

Performance

Nginx is a highly performant web server that can act as a proxy. When used as a reverse proxy Nginx help significantly with increasing the performance of web services. How does it do that?

Event Loop

Basically traditional servers use multiple processes or threads to manage incoming requests and are usually blocking by nature, Nginx used Event loop to manage multiple requests in a single thread and is by design non-blocking.

Load Balancing

With the ability to serve tens of thousands of clients concurrently, Nginx can distribute the requests to multiple application servers upstream. Since the role of a reverse proxy is to serve content while the role of application servers is to execute business logic, which usually takes longer, Nginx is able to serve many more clients increasing content serving capacity.

Content Acceleration

A reverse proxy can provide additional services such as content compression which reduces the size of the data in transit. This results in faster communication and thus better overall user experience. or SSL encryption to take load of the application servers.

Caching

Nginx, configured as a reverse proxy also has the ability to cache content from Origin servers. By caching content it skips the trip to the upstream application servers and returns the content to the clients in a much shorter duration.

Reliability

The ability to allow distributing load among multiple application servers increases the overall reliability of the system because even if one of the servers was taken offline, other servers are still serving requests thus increasing the overall reliability of the infrastructure.

Security

Sitting in front of the application servers, a reverse proxy is able to provide anonymity by hiding their identities which increases overall security. This forms an additional layer against security attacks.

Setup Nginx as a Reverse Proxy

I am going to assume that you have the following already in place.

  • Application server installed and running: This can be Apache HTTPD or Tomcat or some other HTTP server.
  • Nginx is installed and running.
Note: I am going to use the domain example.com in all of the code files. You can change this to any other domain that you are using.

Setup Domain Example.com

If you are using this domain we need to make sure that you are able to ping it. What that means is that a lookup will resolve the domain name to an IP address.

Add domain to Hosts file

Open the hosts file and add an entry for example.com

Windows File Location

C:\Windows\system32\driver\etc\hosts

Linux---BSD File Location

/etc/hosts

Add the following line to the end of the file.

127.0.0.1    example.com

We have added the domain so it will be resolved to the local IP.

Setup Application Server

I am assuming you already have the upstream application server configured and listening on the domain you are setting up. If that is the case you can skip this section.

If you don’t have the virtual host setup, follow the instructions below for setting up Apache HTTPD and configure it to start serving the example.com domain. I will set it up to listen on port 90.

On Windows add the following line to {Apache HTTPD Server Path}\conf\extra\httpd-vhosts.conf.

<VirtualHost *:90>                                      *** Line 1
	ServerAdmin webmaster@localhost
	ServerName  example.com                         *** Line 2

	DocumentRoot C:/temp/www                        *** Line 3
	<Directory C:/temp/www>                         *** Line 3                 
		Options FollowSymLinks MultiViews
		Require all granted
		AllowOverride All
	</Directory>

	ErrorLog logs/localhost.log
	LogLevel warn

	CustomLog logs/localhost-access.log combined
</VirtualHost>

On Linux system you need to add a file to the folder /etc/apache2/sites-available. Add the following lines to the file. (I have named my file example.conf.

<IfModule mod_ssl.c>
        <VirtualHost _default_:90>                          *** Line 1
                ServerAdmin webmaster@localhost
                ServerName  freeservermonitor.com           *** Line 2

                DocumentRoot /var/www/example/              *** Line 3
                <Directory /var/www/example>               *** Line 3
                        Options FollowSymLinks MultiViews
                        AllowOverride All
                        Order allow,deny
                        allow from all
                </Directory>

                ErrorLog ${APACHE_LOG_DIR}/fsm.log
                CustomLog ${APACHE_LOG_DIR}/fsm-access.log combined

        </VirtualHost>
</IfModule>

On Linux run the following commands to activate the domain.

root@s1 /etc/apache2/sites-available # sudo a2ensite example.conf      *** This enables the new Apache virtual host

root@s1 /etc/apache2/sites-available # sudo service apache2 restart    *** Restarts Apache HTTPD server to start serving pages for the domain.

Let’s look at what you may need to change in this code.

  • Line 1: I am setting up Apache to listen on port 90.
  • Line 2: Domain name you are using. In my case, I am using example.com.
  • Line 3: Name of the folder where you have the HTML files.

Save the updates to the file and restart Apache HTTPD.

You should be able to open a browser and go to the URL http://example.com:90. The contents will be whatever you have put in the index.html file.

This completes the setup of the application server. If you already have a server running on another machine, just note down the URL for that as we will need it later.

Setup Nginx Reverse Proxy

In the earlier step, I have set up Apache to start serving example.com on port 90. In this setup, I will configure Nginx as a reverse proxy.

First we need to create a server entry in the Nginx config file.

On Windows edit the file {Nginx install path}\config\nginx.conf.

On Linux create a new file under /etc/nginx/sites-available/.

Add the following lines to the file inside the http {} block.

server {
        listen                          80;
        server_name                     example.com;

        location / {
                proxy_pass              http://127.0.0.1:90;
	        proxy_redirect          http://127.0.0.1:90 http://$host;
		proxy_set_header  	Host $host;
		proxy_set_header    	X-Real-IP $remote_addr;
		proxy_set_header    	X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header    	X-Forwarded-Proto $scheme;        
		proxy_read_timeout  	90;
        }
}

Basically in this config, I am setting the server to listen on port 80 for domain example.com and then proxy request to URL http://127.0.0.1:90.

I am passing the Host using proxy_set_header. Using this value Apache HTTPD is able to route the request to the correct domain.

Restart Nginx

With all config changes in place, we need to restart the Nginx server with reverse proxy on for domain example.com.

One Windows…

C:\> cd {nginx home}

C:\apps\nginx> nginx.exe -s stop       *** This stops the Nginx server.

C:\apps\nginx> start nginx.exe         *** Restart the Nginx server

On Linux, you need to first activate the site and then restart the Nginx server.

root@s1 /etc/nginx/sites-available # ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example

roo2@s1 /etc/nginx/sites-available # sudo service nginx restart

This completes the first part of this tutorial, that is your reverse proxy is ready to serve requests on http://example.com and forward it to http://example.com:90.

Enter the URL in the browser to see the results.

Setup Nginx as a Reverse Proxy Caching Server

Now we move to the part where we set up Nginx as a caching server.

To enable caching we don’t need to worry about the application server. In our case that is Apache HTTPD.

We just need to go back to the Nginx config file /etc/nginx/sites-enabled/example and edit this one file. I will keep the existing code in there but add settings for Caching. With the changes the file contents will be:

server {
        listen       80;
        server_name  example.com;

        location / {
            proxy_pass              http://127.0.0.1:90;
	    proxy_redirect          http://127.0.0.1:90 http://$host;
            proxy_set_header        Host $host;
	    proxy_set_header        X-Real-IP $remote_addr;
	    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
	    proxy_set_header        X-Forwarded-Proto $scheme;        
	    proxy_read_timeout      90;                               
	    proxy_cache             tmpcache;                       
	    proxy_cache_key         $scheme://$host$request_uri;
	    proxy_cache_methods     GET HEAD POST;                
            proxy_cache_valid       200  1d;                      
	    proxy_cache_use_stale   error timeout invalid_header updating http_500 http_502 http_503 http_504;
  
        }
}

Let’s go over the details of what I added to the file.

  • Line 13: Proxy cache core settings. tmpcache contains properties that define where cache files are stored and other related info.
  • Line 14: If you have multiple websites being served through a single Nginx reverse proxy server, the proxy_cache_key provides sort of a unique has to keep content from multiple domains separated. If this is missing then there will be cache clashes and the wrong content will be sent to the clients. If you are setting up only one domain on Nginx then you can delete this line.
  • Line 15: Describes which HTTP methods to cache. Although I have added POST here, most do not like to cache POST requests. It is up to you as to which methods you want to cache.
  • Line 16: How long to cache the content.
  • Line 17: Tells Nginx what to do in case there are errors on the upstream application servers. For example, in the case of 503 Nginx will serve content from the cache instead of sending the HTTP 503 error to clients.

Setting up PROXY_CACHE key

The proxy_cache value is set outside of the server{} entries. It is part of the http{} config. For my setup, I am using the following entry.

 proxy_cache_path /tmp/nginxcache levels=1:2 keys_zone=tmpcache:1000m;

With the code shown above I am telling Nginx to store all cache files in the /tmp/nginxcache folder. Cache size I have setup is 1,000 megabytes. The important part is the keys_zone value which is basically what I use in the server{} section to inform where to store cache files for a particular domain.

You can have multiple proxy_cache_path entries and can use different paths for different domains. If this is the method you choose to setup your reverse proxy cache then you don’t need to set proxy_cache_key value.

Testing the Changes

Earlier we verified that the reverse proxy is working. This time we will do the same. either open a new browser and go to http://example.com or just refresh your existing tab if you already have it open.

Assuming the web page loads just fine you need to go to the tmpcache folder, which in my case is /tmp/nginxcache. Run the following commands to view the contents of the cache.

root@s1 /tmp/nginxcache # ls -R
.:
2

./2:
21

./2/21:
d3ace085341e571deecd636ff0350212
root@s1 /tmp/nginxcache #

I did a ls -R to see all files recursively. From the output above I can see that there is one object cache in the folder /tmp/nginxcache/2/21 named d3ace085341e571deecd636ff0350212.

If you view the content of the cached object in your editor, you will find some unreadable text followed by readable content for the cached object.

In any case mere presence of this folder structure confirms that your reverse proxy is working with caching activated.

Should I Use Nginx Reverse Proxy with Caching?

Most definitely. I use it for all my websites including the current one you are looking at. Even though I sit behind Cloudflare, which is a reverse proxy itself, Nginx allows me to locally load balance all of my web servers.

It is easy to set up and something you should have enabled on anything you are hosting, especially if you are interested in securing your Application Servers.

Checkout our NGINX server page for additional posts and tutorials.

Let me know if you have any questions in the comments. I will be happy to help.

Resources

Nginx Proxy Module: Here you will find information on all variables that you can use for configuring your caching proxy server.

Nginx+ reverse proxy documentation.

Apache HTTPD Server

Nginx Server Download

Sample Nginx Config File for Windows on GitHub.

Leave a Comment