This tutorial will go over how to set up an Nginx reverse proxy in Debian 9 Stretch. Nginx can be installed in front of an Apache that serves WordPress content. Nginx (enginex) is a lightweight and fast web server with a smaller memory footprint than Apache, which can also serve as a proxy cache to deliver static content. This has the potential to significantly speed up the delivery of web content.

You can use this reverse proxy setup to have Nginx directly serving cached static content and minimising the work passed onto Apache, which should be only dynamic content. Although a powerful and flexible server, Apache has a large memory footprint and can become slow under load.

I am assuming you have a LAMP server set up, and maybe you’ve installed a WordPress website in it. I will be using this very setup as an example.

We need to make a couple of changes before installing Nginx. If we tried to install it straight away, it would complain that it can’t bind to port 80 and refuse to start (this is because Apache is already bound to port 80). Firstly we need to tell Apache to listen in a different port, and then we need to modify all the virtual hosts to listen in the same port, in our case we’ll use 8080.

root@system:~# nano /etc/apache2/ports.conf

You need to change the listening port to port 80. You can comment out the SSL ports since we can deploy SSL at the proxy level with Nginx.

Listen 8080

#<IfModule ssl_module>
#	Listen 8443
#</IfModule>

#<IfModule mod_gnutls.c>
#	Listen 8443
#</IfModule>

After this, edit the virtual host files:

root@system:~# nano /etc/apache2/sites-available/example.com.conf

In the first line, change

<VirtualHost *:80>

With:

<VirtualHost *:8080>

If you have other virtual hosts, you need to change them all to listen on port 8080. After this reload Apache configs with

root@system:~# systemctl reload apache2

Now we can install Nginx without port conflicts:

root@system:~# apt install nginx

Once the installation is done, let’s create a new Nginx virtual host file:

root@system:~# nano /etc/nginx/sites-available/proxy

We’re going to use this single virtual host to forward all content to Apache. Let’s include a mostly empty server block to proxy requests on:

server {
	listen 80;
	server_name example.com www.example.com; \# Add all your domain names here

	location / {
		proxy_pass http://localhost:8080;
		proxy\_set\_header X-Real-IP $remote_addr;
		proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
		proxy\_set\_header Host $host;
		proxy\_set\_header X-Forwarded-Proto $scheme;
	}
}

Save and close. Now we need to remove the default server from sites-enabled, and create a symlink to the proxy virtual host:

root@system:~# rm /etc/nginx/sites-enabled/default
root@system:~# ln -s /etc/nginx/sites-available/proxy /etc/nginx/sites-enabled/proxy

We also need to install a module so Apache logs show the original IP address of each request. Without this module, all requests will appear to come from localhost (127.0.0.1). If you use Fail2ban or Logwatch to monitor logs (you should), you’ll need to know the original IP of requests.

root@system:~# apt install libapache2-mod-rpaf

Let’s reload the Nginx config to enable the changes we’ve just made:

root@system:~# systemctl reload nginx

Now, if all goes well, you should see your site being served from the Nginx reverse proxy!

If you have multiple sites and you may want to modify configurations independently in the future, it makes more sense to have separate virtual hosts for each domain name. You should create separate files in /etc/nginx/sites-available (and symlink to them in /etc/nginx/sites-enabled). For example:

Virtual host file for example1.com (/etc/nginx/sites-available/example1)

server {
	listen 80;
	server_name example1.com www.example1.com;

	location / {
		proxy_pass http://localhost:8080;
		proxy\_set\_header X-Real-IP $remote_addr;
		proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
		proxy\_set\_header Host $host;
		proxy\_set\_header X-Forwarded-Proto $scheme;
	}
}

Virtual host file for example2.com (/etc/nginx/sites-available/example2)

server {
	listen 80;
	server_name example2.com www.example2.com;

	location / {
		proxy_pass http://localhost:8080;
		proxy\_set\_header X-Real-IP $remote_addr;
		proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;
		proxy\_set\_header Host $host;
		proxy\_set\_header X-Forwarded-Proto $scheme;
	}
}

Once you have created your virtual hosts files, don’t forget to symlink them in sites-enabled and reload nginx:

root@system:~# ln -s /etc/nginx/sites-available/example1 /etc/nginx/sites-enabled/example1
root@system:~# ln -s /etc/nginx/sites-available/example2 /etc/nginx/sites-enabled/example2
root@system:~# systemctl reload nginx

If everything worked well, we may want to move to the next stage, which is using Nginx to serve static content.