
Diagnose an Nginx 502 in 10 Minutes: A DevOps Incident
July 10, 2026 · 11 min read
14:03. Monitoring reports the site returning "502 Bad Gateway" 100% of the time. In this post you'll meet the core Linux commands not as a list to memorize, but in the order you'd actually use them to solve a real incident. Goal: find root cause in 10 minutes.
Symptom: what does a 502 actually mean?
A 502 Bad Gateway means Nginx is up but can't reach the upstream (your app server) behind it. So the problem is usually not in Nginx — it's in the upstream. This mental model dictates the diagnosis order.
Note
502 = upstream unreachable. 504 = upstream too slow (timeout). 503 = service temporarily down. The exact code tells you where to look.
The 10-minute diagnosis flow
- 1Read the Nginx error log — what's the upstream error? (journalctl)
- 2Is the upstream listening? (check the port with ss)
- 3Is the upstream process alive or crashed? (systemctl / ps)
- 4Call the upstream directly — is it healthy? (curl)
- 5Are we out of resources? (free, top, df)
- 6Any permission / socket issue? (ls -l, SELinux)
Step by step in the terminal
1) Nginx log: what's the exact error?
$ sudo journalctl -u nginx --since "10 min ago" --no-pager | tail -n 3connect() failed (111: Connection refused) while connecting to upstream,upstream: "http://127.0.0.1:3000/", request: "GET / HTTP/1.1"# → 'Connection refused' = nothing is listening on the upstream port. Clear lead.
2) Is the upstream listening?
$ sudo ss -ltnp | grep :3000# (no output) → NO process listening on 3000. The app is down.$ sudo ss -ltnp | grep :80LISTEN 0 511 0.0.0.0:80 users:(("nginx",pid=712)) # nginx itself is up
3) Did the app process crash?
$ systemctl status myapp --no-pager● myapp.service - Node APIActive: failed (Result: exit-code) since 14:02Process: 991 ExecStart=/usr/bin/node server.js (code=exited, status=1)$ sudo journalctl -u myapp --since "15 min ago" | tail -n 2Error: listen EADDRINUSE / Cannot find module 'pg' # root cause lives here
4) Call the upstream directly
$ curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/healthcurl: (7) Failed to connect to 127.0.0.1 port 3000: Connection refused# → We took Nginx out of the equation; the upstream truly isn't answering.
5) Out of resources? (a common crash cause)
$ free -htotal used freeMem: 3.8Gi 3.7Gi 84Mi # memory exhausted → the OOM killer may have killed the process$ df -h /Filesystem Size Used Avail Use%/dev/root 20G 20G 0 100% # disk 100% → app can't write logs/temp, crashes$ dmesg -T | grep -i "killed process" | tail -n 1[Wed] Out of memory: Killed process 991 (node) # ✓ proof: OOM
Warning
Common mistake: reaching for "nginx -s reload" or "systemctl restart nginx". Nginx is already healthy; restarting it won't fix a 502 — it only delays the symptom. Fix the upstream first.
6) Fix and verify
$ sudo systemctl restart myapp$ sudo ss -ltnp | grep :3000LISTEN 0 511 127.0.0.1:3000 users:(("node",pid=1042)) # ✓ upstream is up$ curl -s -o /dev/null -w "%{http_code}\n" https://site.com200 # ✓ the 502 is gone
Troubleshooting checklist
- journalctl -u nginx → the exact 'connect() failed' message
- ss -ltnp → is the upstream port being listened on
- systemctl status <app> → is the process failed/active
- curl 127.0.0.1:<port> → test the upstream without Nginx
- free -h / df -h / dmesg → OOM or disk-full crash
- Permissions/SELinux: getenforce, ls -l <socket>, setsebool httpd_can_network_connect
Mini task
Run a simple HTTP service on port 3000 in a VM or container and put an Nginx reverse proxy in front. Then stop the service and observe the 502. Apply the 6 steps above in order and confirm the root cause is 'connection refused'. Bonus: push the service into OOM and find the proof in dmesg.
Hands-on task — try it in your browser
It's not about memorizing commands — it's using them in the right order on a real incident. Cloudpuz labs give you exactly that diagnosis reflex with broken scenarios in an interactive terminal.
Official sources
Last verified: 2026-07-17
Frequently Asked Questions
What does a 502 Bad Gateway error mean?
A 502 Bad Gateway means Nginx is up but can't reach the upstream (your app server) behind it. So the problem is usually not in Nginx — it's in the upstream. This mental model dictates the diagnosis order: look at the upstream first.
What is the difference between 502, 503, and 504 errors?
502 means the upstream is unreachable, 504 means the upstream is too slow (timeout), and 503 means the service is temporarily down. The exact code tells you where to look.
How do you diagnose an Nginx 502 error?
In order: read the upstream error in the Nginx log with `journalctl -u nginx`; check whether the upstream port is being listened on with `ss -ltnp`; see if the process is alive or crashed with `systemctl status <app>`; test the upstream directly without Nginx using `curl 127.0.0.1:<port>`; check for resource exhaustion like OOM or a full disk with `free -h`, `df -h`, and `dmesg`; finally check for permission/SELinux issues.
How do you check which process is listening on a port?
Use `sudo ss -ltnp | grep :<port>`. If there is no output, no process is listening on that port, which indicates the upstream app is down. If the output shows a process name and PID (for example nginx or node), the process is up.
Does restarting Nginx fix a 502 error?
No. In a 502 situation Nginx is already healthy; running `nginx -s reload` or `systemctl restart nginx` won't fix it and only delays the symptom. You must fix the upstream first.
Reading isn't enough — do it.
Practice these topics in an interactive terminal in your browser.