location / { proxy_pass http://127.0.0.1:3000; } plus the Host, X-Real-IP, X-Forwarded-For and X-Forwarded-Proto headers, then run sudo nginx -t and sudo systemctl reload nginx. Your app keeps listening only on 127.0.0.1, and Nginx serves it on ports 80 and 443 with your domain and HTTPS.
Before you start
- Install Nginx and point your domain at the server (point a domain).
- Start your app and check it answers locally, for example
curl http://127.0.0.1:3000. This guide uses port3000and the domainapp.example.com. - Use a user with
sudo. If you areroot, leave outsudo.
How to configure the reverse proxy
1
Create the server block
Ubuntu / Debian: The
/etc/nginx/sites-available/app.example.com. AlmaLinux / Rocky: /etc/nginx/conf.d/app.example.com.conf.map block and the Upgrade / Connection headers let WebSocket connections through. Define the map only once across all your config files.2
Enable the site (Ubuntu / Debian only)
3
Allow Nginx to connect to the app (AlmaLinux / Rocky only)
SELinux blocks Nginx from opening network connections by default. Allow it:
4
Test and reload
What each line does
How to check it worked
curl http://127.0.0.1:3000. Then open http://app.example.com in a browser.
If you see 502 Bad Gateway, Nginx could not reach the app. The error log names the reason, for example connect() failed (111: Connection refused) while connecting to upstream. See fix 502 Bad Gateway.
How to add HTTPS
Run Certbot for the proxied domain:listen 443 ssl lines and the certificate to this server block. See free SSL with Certbot.
How to proxy long requests or large uploads
Nginx closes a proxied request if the app sends nothing for 60 seconds (proxy_read_timeout) and refuses request bodies over 1 MB (client_max_body_size). Raise them only where needed:
Frequently asked questions
My app still logs 127.0.0.1 as the client IP. Why?
The app must be told to trust the proxy and readX-Forwarded-For. In Express, set app.set('trust proxy', 'loopback'); in Django or Flask, use the framework’s proxy settings. Only trust the header from 127.0.0.1.
Can I proxy a sub-path like example.com/app/?
Yes:location /app/ { proxy_pass http://127.0.0.1:3000/; }. The trailing slash on proxy_pass strips /app/ before the request reaches the app. Many apps also need a base-path setting.
Can Nginx balance across several app instances?
Yes. Defineupstream app_servers { server 127.0.0.1:3000; server 127.0.0.1:3001; } in the http context and use proxy_pass http://app_servers;.
Is Caddy easier for this?
Caddy needs one line,reverse_proxy 127.0.0.1:3000, and adds HTTPS by itself. See install Caddy.
Related guides
VPS and dedicated server guides
Every server guide in one place.
Node.js with PM2
Run the app behind the proxy.
Python with Gunicorn
Flask and Django behind Nginx.
Fix 502 Bad Gateway
When the upstream fails.
Free SSL with Certbot
HTTPS for your proxy.
Checked against the official nginx proxy module documentation, nginx WebSocket proxying guide and Red Hat Enterprise Linux 9 Nginx guide on 4 November 2026; proxy configuration tested on Ubuntu 24.04 LTS (Nginx 1.24.0) with a Node.js app. Commands can differ on other distributions or releases.
Need Extra Help?
If you encounter any issues, our support team is ready to assist:- Live Chat: Quick assistance via our website.
- Support Ticket: Open a Ticket
- Discord: Join our Community
- Email: support@freakhosting.com
Last Updated: November 2026