Overview

Nginx is the most widely deployed reverse proxy on the web. It sits in front of your application server, handles TLS termination, serves static files, and forwards dynamic requests. This tutorial walks through a production-ready reverse proxy configuration.

What Is a Reverse Proxy?

A reverse proxy accepts client requests and forwards them to one or more backend servers. The client never talks to the backend directly.

BenefitExplanation
TLS terminationCertificates and encryption handled in one place
Load balancingDistribute traffic across multiple app instances
Static file servingNginx serves assets far faster than most app servers
SecurityBackend servers are not exposed to the internet

Install Nginx

# Ubuntu / Debian
sudo apt update
sudo apt install nginx

# CentOS / RHEL
sudo yum install nginx
sudo systemctl enable --now nginx

Basic Reverse Proxy Configuration

Create /etc/nginx/sites-available/myapp:

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

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Enable the site and reload:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Key proxy_set_header Directives

HeaderPurpose
HostPreserves the original hostname for the backend
X-Real-IPClient IP address
X-Forwarded-ForChain of proxy IPs for logging
X-Forwarded-ProtoTells the backend whether the original request was HTTP or HTTPS
Upgrade / ConnectionRequired for WebSocket support

Serving Static Files Alongside the Proxy

location /static/ {
    alias /var/www/myapp/static/;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

location / {
    proxy_pass http://127.0.0.1:3000;
}

Adding HTTPS with Let's Encrypt

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Certbot is available from the Certbot official site. It automatically updates the Nginx config and installs a renewal timer.

Common Configuration Errors

ErrorCauseFix
502 Bad GatewayBackend not running or wrong portVerify the app is listening on the configured port
504 Gateway TimeoutBackend response exceeds proxy timeoutIncrease proxy_read_timeout
Redirect loopBackend redirects to HTTPS but X-Forwarded-Proto is missingAdd the header shown above