All Snippets

Nginx Reverse Proxy Setup for Any App

Configure Nginx as a reverse proxy with SSL termination, WebSocket support, and security headers for production deployments.

A reverse proxy sits in front of your application server, handling SSL, load balancing, caching, and security headers. This guide covers a production-ready Nginx reverse proxy config from scratch.

Prerequisites

  • A Linux server (Ubuntu/Debian or RHEL/CentOS)
  • A domain name pointing to your server's IP
  • Your app running on a local port (e.g., localhost:3000)

Install Nginx

Ubuntu / Debianbash
1
sudo apt update && sudo apt install -y nginx
2
sudo systemctl enable --now nginx
RHEL / CentOS / Amazon Linuxbash
1
sudo yum install -y nginx
2
sudo systemctl enable --now nginx

Basic Reverse Proxy Config

/etc/nginx/sites-available/myapp.confnginx
1
server {
2
    listen 80;
3
    server_name myapp.example.com;
4
 
5
    location / {
6
        proxy_pass http://127.0.0.1:3000;
7
        proxy_set_header Host $host;
8
        proxy_set_header X-Real-IP $remote_addr;
9
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
10
        proxy_set_header X-Forwarded-Proto $scheme;
11
    }
12
}
Enable the sitebash
1
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
2
sudo nginx -t && sudo systemctl reload nginx

Add SSL with Let's Encrypt

Use certbot to get free SSL certificates:

Install certbot and get a certificatebash
1
sudo apt install -y certbot python3-certbot-nginx
2
sudo certbot --nginx -d myapp.example.com

Certbot auto-modifies your Nginx config to add SSL. It also sets up auto-renewal via a systemd timer. Verify with sudo certbot renew --dry-run.

Production-Hardened Config

/etc/nginx/sites-available/myapp.conf (full)nginx
1
server {
2
    listen 443 ssl http2;
3
    server_name myapp.example.com;
4
 
5
    ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
6
    ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
7
 
8
    # Security headers
9
    add_header X-Frame-Options "SAMEORIGIN" always;
10
    add_header X-Content-Type-Options "nosniff" always;
11
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
12
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
13
 
14
    # Proxy settings
15
    location / {
16
        proxy_pass http://127.0.0.1:3000;
17
        proxy_http_version 1.1;
18
        proxy_set_header Host $host;
19
        proxy_set_header X-Real-IP $remote_addr;
20
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
21
        proxy_set_header X-Forwarded-Proto $scheme;
22
 
23
        # WebSocket support
24
        proxy_set_header Upgrade $http_upgrade;
25
        proxy_set_header Connection "upgrade";
26
 
27
        # Timeouts
28
        proxy_connect_timeout 60s;
29
        proxy_send_timeout 60s;
30
        proxy_read_timeout 60s;
31
    }
32
}
33
 
34
# Redirect HTTP to HTTPS
35
server {
36
    listen 80;
37
    server_name myapp.example.com;
38
    return 301 https://$server_name$request_uri;
39
}

Common Proxy Headers Explained

HeaderPurpose
X-Real-IPPasses the client's real IP to your app
X-Forwarded-ForChain of all proxies the request passed through
X-Forwarded-ProtoWhether the original request was http or https
HostPreserves the original Host header from the client
Upgrade / ConnectionRequired for WebSocket connections to work

Useful Commands

Test, reload, and debugbash
1
# Test config syntax before reloading
2
sudo nginx -t
3
 
4
# Reload without downtime
5
sudo systemctl reload nginx
6
 
7
# Watch access logs in real-time
8
sudo tail -f /var/log/nginx/access.log
9
 
10
# Watch error logs
11
sudo tail -f /var/log/nginx/error.log

Always run nginx -t before reloading. A syntax error in the config will take down all sites on the server if you use systemctl restart instead of reload.

For load balancing across multiple app instances, use an upstream block. See the Nginx upstream docs for round-robin, least-connections, and IP-hash strategies.