A reverse proxy is a front door. Visitors talk to Nginx on port 80 (or 443). Nginx then asks your app—often Node.js or Express on 127.0.0.1:3000—for the page, and sends the answer back.
Public port: Nginx on 80/443.
Private port: your app on localhost only.
Directive:proxy_pass chooses the upstream.
Beginner tip.
This walkthrough uses Ubuntu-style commands (common on Amazon Linux alternatives and Ubuntu EC2 AMIs). Package names can differ slightly on Amazon Linux—use the same ideas.
Why it matters
In Simple Words
What problem does it solve?
EC2 deploy demos often bind Node to port 80 with elevated privileges. A reverse proxy is the cleaner habit: Node on 3000, Nginx on 80, visitors never type :3000.
sites-enabled is what Nginx actually loads (symlink pattern on Ubuntu).
nginx -t must say the syntax is ok before reload.
reload applies the new config with less downtime than a full restart.
Amazon Linux note.
You may edit /etc/nginx/conf.d/my-app.conf instead of sites-available. Same server { } content; still run nginx -t and reload.
Step 5 — Test from Your Browser
Open http://YOUR_PUBLIC_IP/ (or your domain if DNS already points here).
You should see the same app that answered on port 3000.
Optional: remove public security-group access to port 3000 so only Nginx is the door.
If you get 502, jump to Common Mistakes below.
How It Works
The browser only knows port 80 now.
Nginx forwards to localhost:3000 and returns the body and status.
Later upgrades: HTTPS (certificates), or move the public door to an ALB + ACM.
Avoid these
Common Beginner Mistakes
502 because Node is down
Run pm2 status and curl 127.0.0.1:3000 on the server before blaming Nginx.
Wrong proxy_pass port
Config says 3000 but the app listens on 8080. Match them exactly.
Skipped nginx -t
A missing semicolon can leave the old site running or block reload. Always test first.
Default site still wins
Remove or disable default in sites-enabled so your proxy config is the one that answers.
Port 80 closed in the security group
SSH works, browser times out. Open TCP 80 (and 443 later).
App still bound only to a public demo on 80
Stop the old “listen on 80 with sudo” process so Nginx can own port 80.
Remember
Key Takeaways
Nginx on 80/443, app on a high localhost port.
proxy_pass is the core reverse-proxy line.
Test the app locally, then test Nginx, then the public URL.
nginx -t then reload after every config change.
One line: install Nginx, proxy_pass to your app, test, reload, then browse port 80.
Frequently Asked Questions
Nginx listens on the public port (usually 80 or 443), receives each visitor request, asks your backend (for example Node on 127.0.0.1:3000) for the response, and returns that response to the visitor.
On Linux, ports below 1024 are privileged. Demos sometimes use sudo with PM2. A reverse proxy lets Node stay on a normal high port while Nginx owns 80/443.
proxy_pass tells Nginx which upstream URL should handle matching requests. A common beginner line is proxy_pass http://127.0.0.1:3000;
Nginx reached the proxy target but got no healthy response. Usually the Node process is down, listening on a different port, or blocked. Check PM2 status and curl localhost:3000 on the server.
No. Start with HTTP on port 80. Add TLS later with a certificate (on AWS you may use ACM on an ALB, or certificates on the instance). Get the reverse proxy working first.
No. This guide runs Nginx on your server. An ALB is a managed AWS load balancer in front of instances. Both can forward traffic; pick one public door for your architecture.