how to setup nginx as a reverse proxy

Setting up a reverse proxy using nginx is easy:

for this how-to i will use debian

1) install nginx:

sudo apt-get install nginx

2) remove the default config (or move somewhere else for reference):

sudo rm /etc/nginx/sites-enabled/default
sudo rm /etc/nginx/sites-available/default

3) copy your certificates to the machine or generate some if using self-signed certificates, for a great lets encrypt certificate how-to click here

4) create a default conf, which probably leads to your webserver:

sudo nano /etc/nginx/sites-available/default-webserver

server {
    listen 443 ssl default_server;
    server_name _;
    ssl on;
    ssl_certificate /etc/nginx/ssl/certs/your-certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/private/your-key.key;
    error_log /var/log/nginx/default-webserver/error.log;
    access_log /var/log/nginx/default-webserver/access.log;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass https://<IP-OF-YOUR-WEBSERVER>;

were the cert paths have to be adjusted to match yours and the ip/hostname of the webserver has to be inserted


listen 443 ssl default_server; creates a virtual host on port 443 which listens for ssl connections and is the default server, so it takes all requests not handled by any other config
server_name _; can also be omitted, only symbolizes the unused server_name directive
location / {} defines an action for the root ( / ) of the current config
proxy_set_header Host $host; sets the host header if your next hop (the webserver) wants to do sni again or is configured to only accept requests for a specific domain
proxy_set_header X-Real-IP $remote_addr; sets the X-Real-IP header to the remote_addr, which is the connecting ip to the reverse proxy
proxy_pass https://<IP-OF-YOUR-WEBSERVER>; instructs nginx to connect to https://<IP-OF-YOUR-WEBSERVER> if a request arrives for this config

note that the backend (your weserver, webapp, whatever) and frontend (the reverse proxy) do not need to be https

5) i prefer to use seperate directorys for each config, in such a case you have to create the directory for the logs:

sudo mkdir -p /var/log/nginx/default-webserver

6) link the config to the sites-enabled directory for nginx to actually use it:

sudo ln -s /etc/nginx/site-available/default-webserver /etc/nginx/sites-enabled/default-webserver

7) test if nginx accepts the config by issuing:

sudo nginx -t

8) if everything is ok, reload nginx:

sudo service nginx reload

you can test the proxy by connection to the ip/hostname of the reverse proxy machine



to use different hosts for different domain names just repeat the steps 3 to 8, but this time set a servername like so:

server {
    listen 443 ssl;
    server_name mysubdomain.domain.tld;
    ssl on;
    ssl_certificate /etc/nginx/ssl/certs/your-certificate.crt;
    ssl_certificate_key /etc/nginx/ssl/private/your-key.key;
    error_log /var/log/nginx/mysubdomain.domain.tld/error.log;
    access_log /var/log/nginx/mysubdomain.domain.tld/access.log;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass https://<IP-OF-YOUR-OTHER-WEBSERVER>;


if you want to use cloudflare as another reverse proxy on top of yours, check out this post to get the real visitor ip for the nginx logs

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.