I did a little write-up on how I achieved reverse proxy nirvana with IIS quite a while ago now. It made things a lot nicer for me. Like, a lot. Then I took it further, and moved to Apache (with certbot, for that sweet SSL).
Now I have a few friends/colleagues/acquaintances who run Nginx (I run Apache in my homelab environment nowadays, which is why I migrated from IIS to Apache), so I figured I’d look into how I can help them achieve a reverse proxy with Nginx instead.
Firstly, you’ll need to have a functional Nginx installation. We’re not covering that here, there are plenty of write-ups about that out there. It’s fairly straightforward to do, and simply requires you have root access to the shell on your server.
Deactivating the default config
Secondly, you’ll need to unlink the default linked configuration/virtualhost file (assuming this is a fresh Nginx instance, not serving other sites. If it’s in use for other sites, then this guide could provide a base to build from but will break the existing site if it’s using the default config file which I strongly recommend against doing).
sudo unlink /etc/nginx/sites-enabled/default
Creating and activating the reverse proxy config file
Now that’s out of the way, we can create a config for the reverse proxy page (I tend to use the name of the site as the name of the config file)
sudo nano /etc/nginx/sites-available/reverse-proxy
In this config file, we will start with something like the following:
server {
listen 80;
server_name site.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
Configuration directives
The configuration consists of a server {...} block that handles all requests matching the specified conditions. It contains the following data:
listen 80. The server listens for incoming HTTP requests on port 80 (the default HTTP port).server_name site.example.comThe domain name for which the server block is responsible. The example uses site.example.com to demonstrate how the reverse proxy works. This needs to be a valid name for the web server to reply to the correct site when it is requested. This is also used by tools like Certbot when requesting SSL certificates.location / {...}. The configuration for the specified URI path. It matches all requests (/) in this case.proxy_pass http://127.0.0.1:8000. The backend server to which NGINX will pass requests to (which is what a reverse proxy does). The example references an alternative service listening on port 8000 on the same server (127.0.0.1:8000) as a replacement backend. This will change depending on what you’re reverse proxy is proxying to – it should be replaced with whatever your internal URL for the service you wish to proxy is.proxy_set_header. The directive for setting HTTP headers for the proxied request. The headers pass to the backend server and provide additional information about the client’s request. The example includes the Host header, the client’s IP address, and the scheme (HTTP or HTTPS).
Replace the port number, server name, and the backend server with the actual data. The example forwards all requests made to site.example.com to the http://127.0.0.1:8000 address.
Save the file and exit nano.
Activating the new config
Now that the file is ready for use, we have to activate it. This is done by linking the file from /etc/nginx/sites-available to /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
With the file activated, we can tell Nginx to test the config with sudo nginx -t.
Assuming this passes successfully, we can make it go live with a restart of Nginx (sudo systemctl restart nginx).
Awesome! Nginx is now running as a proxy, which means that (assuming your network is pointing traffic to the right location with port forwards and DNS and such), you should be able to browse to the address you specified in the config and you’ll get whatever the proxied application was using the new ‘pretty’ URL. Much nicer.
It also means you can set up an SSL connection to secure it – but that’s a topic for another writeup (maybe). For now, the magic term is “certbot” – as it can automate it and take most of the pain away.