Linux VPS

Set up Nginx as a reverse proxy on a Linux server

Install Nginx on Ubuntu or AlmaLinux and configure it as a reverse proxy for an app on a local port, with correct headers, WebSocket support and free HTTPS from Let's Encrypt.

IntermediateLinux VPS3 min read

An Nginx reverse proxy sits in front of your application, accepts visitors on ports 80 and 443, and forwards requests to an app listening on a local port such as 3000 or 8080. It handles HTTPS, compression and static files so your app does not have to. This guide sets up an Nginx reverse proxy on a fresh Linux VPS.

Before you start

  • A Linux VPS running Ubuntu 22.04/24.04 or AlmaLinux/Rocky 8 or 9, with root or sudo access.
  • A domain whose A record points to the server's IP.
  • An app already running locally, for example on 127.0.0.1:3000.
  • Ports 80 and 443 open in your firewall.

Install Nginx

  1. On Ubuntu or Debian:
    sudo apt update && sudo apt install -y nginx
  2. On AlmaLinux or Rocky Linux:
    sudo dnf install -y nginx && sudo systemctl enable --now nginx
  3. Check it runs: systemctl status nginx, then open http://your-server-ip and you should see the Nginx welcome page.

Create the reverse proxy configuration

  1. Create a site file. On Ubuntu use /etc/nginx/sites-available/app.example.com; on AlmaLinux use /etc/nginx/conf.d/app.example.com.conf.
  2. Add this server block, replacing the domain and port:
    server {
        listen 80;
        server_name app.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";
            proxy_read_timeout 60s;
        }
    }
  3. On Ubuntu, enable the site:
    sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
  4. Test the syntax and reload:
    sudo nginx -t && sudo systemctl reload nginx

The X-Forwarded-* headers tell your app the visitor's real IP and that the original request used HTTPS. The Upgrade and Connection headers let WebSockets pass through.

Allow the proxy on SELinux (AlmaLinux/Rocky)

If you get a 502 error on a RHEL-family server, SELinux may block Nginx from connecting to the app port. Allow it with:

sudo setsebool -P httpd_can_network_connect 1

Add free HTTPS with Let's Encrypt

  1. Install Certbot with the Nginx plugin: sudo apt install -y certbot python3-certbot-nginx (on AlmaLinux enable EPEL first, then sudo dnf install -y certbot python3-certbot-nginx).
  2. Request and install the certificate:
    sudo certbot --nginx -d app.example.com
  3. Choose to redirect HTTP to HTTPS when asked. Renewal runs automatically; test it with sudo certbot renew --dry-run.

What to check afterwards

  • curl -I https://app.example.com returns your app's response, not a 502.
  • Your app logs show real visitor IPs, not 127.0.0.1. Many frameworks need a "trust proxy" setting for this.
  • The app port is not reachable from outside: bind the app to 127.0.0.1 or block the port in the firewall.

Troubleshooting

  • 502 Bad Gateway: the app is not running or listens on a different port. Check with ss -tlnp | grep 3000 and read /var/log/nginx/error.log.
  • 504 Gateway Timeout: the app is too slow; raise proxy_read_timeout or fix the slow request.
  • Redirect loop after HTTPS: the app does not see X-Forwarded-Proto and keeps redirecting to HTTPS; enable its proxy trust setting.
  • 413 Request Entity Too Large: add client_max_body_size 50m; in the server block.

FAQ: Nginx reverse proxy

Why use a reverse proxy instead of exposing the app directly?

It centralises HTTPS, lets several apps share ports 80/443 by domain name, serves static files efficiently and hides the app from direct traffic.

Can Nginx proxy to several apps?

Yes. Add one server block per domain, or several location blocks with different proxy_pass targets.

Can I do this on cPanel hosting?

On shared hosting you cannot edit Nginx, but Node.js apps can run through the cPanel Node.js selector with LiteSpeed in front.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.