Nginx Reverse Proxy with SSL for Multiple Apps
Web Infrastructure

Nginx Reverse Proxy with SSL for Multiple Apps

  • AuthorTimothy M.
  • Date
  • Time18 minutes

Prerequisites

  • Ubuntu 22.04 or Debian 12 server
  • A domain with DNS A records pointing to your server
  • At least one backend app (Node, Python, etc.)
  • Sudo privileges

Step 1: Install Nginx

bash
sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx --no-pager

Step 2: Open Firewall Ports

bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

Step 3: Create Upstream Targets

Assume two local apps are listening on ports 3000 and 4000.

bash
sudo tee /etc/nginx/conf.d/upstreams.conf >/dev/null <<'EOF'
upstream app_main {
    server 127.0.0.1:3000;
}

upstream app_api {
    server 127.0.0.1:4000;
}
EOF

Step 4: Create Site Configuration

bash
sudo tee /etc/nginx/sites-available/example.conf >/dev/null <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name app.example.com api.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name app.example.com;

    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    location / {
        proxy_pass http://app_main;
        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;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    location / {
        proxy_pass http://app_api;
        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;
    }
}
EOF

Step 5: Enable Config and Validate

bash
sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/example.conf
sudo nginx -t
sudo systemctl reload nginx

Step 6: Install Certbot and Issue Certificates

bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com -d api.example.com --redirect --agree-tos -m admin@example.com --no-eff-email

Step 7: Verify Auto-Renewal

bash
systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Step 8: Harden TLS (Optional but Recommended)

bash
sudo tee /etc/nginx/snippets/ssl-params.conf >/dev/null <<'EOF'
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
EOF

"A reverse proxy is not just routing. It is your first production control point for security, observability, and reliability."

Technical Author

Timothy M.

Timothy M.

Support and server administration. Writes the work on the host: packages, services, and what to check when a machine misbehaves.