In the age of docker, snap and other containerization systems, reverse proxies become more important for every day web applications. Many frameworks like ASP.NET Core also come with an embedded webserver. This comes with a number of problems:

  • Those embedded servers are usually not very good at serving static content
  • HTTP is on port 80, HTTPS is on port 443, those ports can only be listened by root
  • Even if one decides to let a docker container run as root and listen to port 80/443, these ports would be blocked by this one web service and it wouldn’t be possible to run multiple web services on one server.
  • Some embedded web servers don’t come with enough security considerations and it would be inadvisable to let them listen to the public internet.

The solution for all these problems are reverse proxies. Both apache and NGINX support reverse proxies. This article covers using reverse proxies on NGINX.

Table of contents

What does a reverse proxy do

nginx reverse proxy (this was created with draw.io)

A reverse proxy takes an HTTP request on one port and forwards it to another port. A web application with an embedded web server or a docker container can therefore run as non-root and listen to a port above 1024, while NGINX will listen to port 80/443 and forward the request to the local web service.

Additionally, NGINX can be set to serve static files more efficiently than other embedded web services.

How to configure the reverse proxy

A reverse proxy is configured as a site like any other website in NGINX.

In the following template it is assumed, that:

  • The web application runs on port 5000
  • The external URL is website.com

Create a site

A configuration file for the reverse proxy needs to be created in /etc/nginx/sites-available, in this case website_com

$ sudo touch /etc/nginx/sites-available/website_com

Create the reverse proxy configuration

The most simple reverse proxy configuration is the following:

server {
       listen 80;
       listen [::]:80;

       # change the website domain 
       server_name website.com www.website.com;

       location / {
               # change the port
               proxy_pass http://127.0.0.1:5000;
       }
}

this will forward all requests to website.com internally to 127.0.0.1:5000 and then forward the request back to the client.

it is also possible to host a website and set up a reverse proxy for a subfolder only:

location /some-path/ {
    proxy_pass http://127.0.0.1:5000;
}

More configuration options can be found on the NGINX documentation

Reload NGINX

Finally, after the configuration is done and everything is set up, the sites-available configuration needs to be linked in sites-enabled and NGINX needs to be reloaded

$ sudo ln -s /etc/nginx/sites-available/website_com /etc/nginx/sites-enabled/website_com
$ sudo systemctl reload nginx