When a Linux-hosted website fails, start at the service boundary rather than changing configuration at random: check nginx and the application service with systemctl status, read their complete systemd journals with journalctl, then match the nginx error log to the HTTP status code. A 502 usually means nginx could not obtain a valid upstream response, a 503 can be an intentional rate or connection limit, and a 504 means the upstream did not produce the next response data before nginx’s read timeout.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
Use this diagnostic order first
The order below keeps you from treating an application failure as an nginx failure, or increasing a timeout when the backend is actually stopped.
As an Amazon Associate I earn from qualifying purchases.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →- Check nginx itself. Run
sudo systemctl status nginx. Read theActiveandResultfields. A result such asexit-codeortimeoutis a clue about how the unit failed. The final lines insystemctl statusare only a recent excerpt; they are not the complete incident record. - Check the backend that nginx proxies to. For a PHP application, for example, run
sudo systemctl status php-fpm. Substitute the service name used by your application. - Read the complete nginx unit journal. Run
sudo journalctl -u nginx. To narrow it to the incident, add a window such as--since "5 minutes ago". After a reboot or restart,sudo journalctl -u nginx -b -1shows the previous boot’s records. To show only error-priority entries for the current boot, usesudo journalctl -u nginx -b -p err. - Read nginx’s error log. The commonly used path is
/var/log/nginx/error.log. Match its wording and timestamp to the request that failed. Do not rely on the status page alone; the error log identifies whether nginx refused a connection, was limited, or waited for an upstream. - Confirm that the backend is listening. Run
ss -tlnpand look for the port or Unix socket configured as nginx’s upstream. If nothing is listening, investigate the backend service and its logs rather than changing proxy settings. - Read the application unit’s own records. For example,
sudo journalctl -u <app-service> --since "5 minutes ago"can reveal a crash, memory exhaustion, or malformed response that nginx can only report as an upstream error. - Apply the fix indicated by the evidence. Depending on the message, that may mean restarting a stopped backend, correcting socket access, addressing an SELinux policy, or adjusting a timeout because the application is demonstrably slow.
Capture a comparable time window
Use the same incident window for every layer. If the browser shows a failure at 14:03, begin with a narrow journal query such as --since "14:00" --until "14:06", then widen it if the service starts logging asynchronously. A five-minute window is useful for a live incident, while journalctl -u nginx -b -1 matters when a restart or reboot has already moved the failure into the previous boot. Save the command output before making changes so that a restart does not remove the timing context.
The Result field is a direction, not a root cause. exit-code means the unit process ended unsuccessfully; timeout means a start, stop, or other unit operation exceeded its limit. Read the surrounding journal lines to learn whether the failure was a configuration problem, a backend dependency, or a repeated crash. The short excerpt printed by systemctl status can omit the first error.
#1 Best Overall
What the main nginx status codes actually mean
| Status | What happened between nginx and the upstream | First evidence to look for | Typical direction of the fix |
|---|---|---|---|
| 502 Bad Gateway | Nginx could not connect to the upstream, received an invalid response, or the upstream closed the connection before completing it. | An error-log line such as connect() failed (111: Connection refused); backend status and listening sockets. |
Start or repair the backend, correct its endpoint, investigate crashes, or fix socket access and policy restrictions. |
| 503 Service Unavailable | Nginx may be healthy and deliberately rejecting traffic because a configured rate or connection limit was reached. | Error-log entries containing limiting requests, the offending IP, and the limit zone name. |
Determine whether the limit is intentional. Do not restart a healthy service automatically; investigate the configured limit and traffic pattern. |
| 504 Gateway Timeout | Nginx connected to the upstream but waited too long for the next part of its response. | The request duration, nginx error log, backend journal, and the effective proxy_read_timeout. |
Repair a slow or stuck backend. Increase the read timeout only when the backend is expected to have a longer quiet interval. |
The code identifies the conversation between nginx and its upstream, not necessarily the original cause. A 502 can begin with a stopped process, a wrong socket, a permission mismatch, an SELinux denial, a crash, or an invalid response. A 503 can be produced before nginx contacts the application. A 504 confirms that nginx reached the upstream far enough to wait for data, but it does not tell you whether the delay came from a query, a blocked worker, or another application dependency. Always pair the code with the log line and timestamp.
Fixing 502 Bad Gateway errors
Confirm that the upstream process is running
A stopped PHP-FPM service is a common example: requests for a PHP application reach nginx, but there is no process available to answer, so nginx returns 502. Check the exact unit with sudo systemctl status php-fpm (or your distribution’s PHP-FPM unit name), then inspect sudo journalctl -u php-fpm --since "5 minutes ago". If the evidence shows the service is stopped or repeatedly failing, restart that backend and verify its status before testing the site again.
A restart is a recovery action, not a diagnosis. If the unit immediately exits, the Result field and the backend journal are more useful than repeating the restart. A service that starts successfully but then fails again under one request points toward an application or resource problem rather than nginx itself.
Check the endpoint nginx is trying to use
Use ss -tlnp to verify that a TCP listener exists on the configured upstream port. For a Unix-socket setup, verify that the socket exists and that the nginx worker’s user and group can access it. A user/group mismatch can produce a 502 even while the backend process appears active; this is a common cause reported in third-party troubleshooting guidance, so confirm it against the permissions on your own server.
Compare the endpoint in the effective nginx location with the endpoint the backend actually opened. A service listening on a different port or socket is functionally the same as a stopped service from nginx’s point of view. Check the matching location rather than an unrelated server block, because a correct setting in a block that does not handle the failing URL has no effect.
Look for crashes, memory pressure, and malformed responses
The backend may be starting and then dying, running out of memory, or emitting a response nginx cannot parse. Search its unit journal around the failed request with journalctl -u <app-service> --since "5 minutes ago". If nginx reports that the upstream closed early, the application log is where you determine whether a worker crashed or aborted while generating the response.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #2
Correlate the nginx line with the backend line instead of treating any nearby message as causal. A crash at the same time as the failed request is stronger evidence than an old startup warning. If the backend repeatedly reaches the same failure point, preserve the logs and investigate the application rather than masking the symptom with nginx restarts.
Check SELinux on RHEL-family systems
On RHEL-family systems, SELinux is a distinct possible cause of an upstream connection failure. A RHEL-focused troubleshooting guide identifies the httpd_can_network_connect boolean as a relevant check. Inspect it with:
getsebool httpd_can_network_connect
Record the result and correlate it with the denial or connection error you observed. Do not disable SELinux or change a boolean merely because the page returned 502; first establish that policy enforcement is blocking the exact connection nginx needs. Treat the policy layer separately from socket permissions: changing a file mode will not resolve a policy denial, and changing a boolean will not create a missing listener.
Fixing 503 Service Unavailable responses
Distinguish deliberate limiting from a dead backend
A 503 is not proof that PHP-FPM or another application service has crashed. A healthy nginx can return 503 when rate or connection limits reject traffic. In the error log, look for limiting requests together with the client IP and the configured zone name. That combination points to nginx’s limit mechanism rather than an upstream outage.
Free tools Windows power users keep installed
One-click scans. No signup required.
If those entries are present, identify whether a legitimate traffic burst, an abusive client, or an overly restrictive limit triggered the response. Changing backend settings will not fix a request that nginx is intentionally refusing before it reaches the backend. Compare the affected IPs and zone name with the limit configuration, then decide whether the limit is an intended safeguard or a configuration error.
If no limiting entry exists
Continue through the same service and backend checks used for a suspected upstream failure: inspect systemctl status nginx, read the full nginx journal, confirm the application listener with ss -tlnp, and inspect the application unit journal. The status code alone cannot identify which layer produced the unavailability.
Do not infer a backend crash solely from a 503 page. If nginx is active, the relevant evidence may be a limit decision, a dependency failure, or an application-side condition. The absence of a limiting line is a reason to continue the layered checks, not a reason to restart every service at once.
Fixing 504 Gateway Timeout responses
Understand what the 60-second default measures
Nginx’s default proxy_read_timeout is 60 seconds. It measures the permitted gap between successive reads from the proxied server, not the total time allowed for the complete response. A response that sends data periodically can therefore run longer than 60 seconds, while a response that sends nothing for 60 seconds can time out even if the final payload would have been valid.
The same 60-second default matters for WebSocket proxying: if the proxied server sends no data during that interval, nginx closes the connection. Long-lived connections need an application-level keepalive or an appropriately chosen read timeout.
This distinction prevents a common measurement error. A request may have a total duration greater than 60 seconds without violating proxy_read_timeout if the upstream keeps sending data. Conversely, a request can fail at roughly 60 seconds while the application is still working, because it produced no next data for the entire interval.
Prove that the backend is slow before raising the timeout
- Confirm the 504 timestamp in the nginx error log.
- Check whether nginx connected successfully; a successful connection followed by waiting points toward a 504, while an immediate refusal points toward a 502.
- Inspect the backend journal for a long-running request, blocked worker, crash, or memory problem.
- Determine whether the application sends any intermediate data during the wait. The read timeout concerns inactivity between reads, not a simple wall-clock total.
If the backend is healthy but legitimately quiet for longer than 60 seconds, set proxy_read_timeout to a value appropriate for that workload in the nginx configuration block that handles the request. A larger value increases how long clients can wait for a stuck request, so it is not a substitute for fixing an unexpectedly slow query or worker.
Choose the smallest increase that accommodates the observed quiet interval, and document why it is needed. The change belongs where the affected request is actually proxied; an edit in an unused block will not alter the failing request. After changing it, reproduce the request and compare the new nginx and backend timestamps.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsRank #4
When a timeout override appears to be ignored
Nginx ticket #1471 described a report of a location-level proxy_read_timeout appearing to be ignored and a 504 after 45 seconds. The ticket was closed as invalid; the reported workaround was to place the directive in the location block that actually matched the request. Treat this as a configuration-scope check, not evidence of a general nginx timeout bug: verify which location handles the failing URL and ensure the setting is applied there.
A reported 45-second failure is not the documented default; it is a clue to inspect the effective configuration and request path. Confirm the selected location, the configured value, and the backend’s actual quiet interval before changing more directives.
Compare the safest first fix
| Observed evidence | Likely layer | Lowest-risk next action | Change to avoid initially |
|---|---|---|---|
| 502 with connection refused | Backend process or endpoint | Check the backend unit and ss -tlnp; repair the listener. |
Raising a timeout. |
| 502 with early upstream close | Application worker or response generation | Read the application journal at the request timestamp. | Repeated nginx restarts. |
| 503 with limiting message | Nginx request or connection limit | Identify the zone and decide whether traffic or limits are appropriate. | Restarting a healthy backend. |
| 504 after a successful connection | Slow or blocked upstream | Measure the quiet interval and inspect the backend. | Increasing the timeout without evidence. |
| Policy-related connection denial | SELinux or another OS policy | Correlate the denial and inspect getsebool httpd_can_network_connect. |
Disabling enforcement blindly. |
Reading the evidence without misdiagnosing the layer
What each command can and cannot tell you
| Evidence | Useful for | Important limitation |
|---|---|---|
systemctl status nginx |
Whether the unit is active, how it exited, and a short recent excerpt. | The excerpt is not the complete log. |
journalctl -u nginx |
Full nginx service history, including records outside the status screen. | You still need the backend journal for application failures. |
/var/log/nginx/error.log |
Request-level upstream, limiting, and timeout messages. | The exact path and logging setup can differ; use the path configured on your host. |
ss -tlnp |
Whether a process is listening on the expected TCP endpoint. | A listener does not prove that the application returns a valid response. |
journalctl -u <app-service> |
Backend crashes, resource failures, and application-side errors. | The correct unit name depends on the application. |
Use timestamps to correlate one request across layers
Pick a single failed request and compare its time in the client, nginx error log, nginx journal, and backend journal. A backend crash at the same moment as a 502 is stronger evidence than a generic “service failed” message from an earlier boot. If you restarted the host or service before investigating, use journalctl -u nginx -b -1 to inspect the previous boot’s records rather than assuming the current journal contains the original failure.
Correlation also prevents mixing incidents. A 503 caused by a limit during a traffic burst should not be explained by a PHP-FPM warning from an hour earlier. Keep the URL, status, client time, nginx time, and backend time together when recording the incident.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
A cautious recovery workflow
- Capture evidence first: save the status output, relevant journal window, nginx error line, and backend status. This prevents a restart from erasing the timing context you need.
- Choose the smallest corrective action: restart only the failed backend, address the socket access problem, investigate the SELinux policy check, or correct the timeout scope.
- Recheck the listener and logs: use
ss -tlnp, then inspect fresh nginx and backend entries. - Test the affected URL again: compare the resulting status and timestamps with the original failure.
- Escalate when the symptom returns: repeated crashes, memory exhaustion, or malformed upstream responses require application-level investigation rather than repeated nginx restarts.
Make one meaningful change at a time when possible. If you restart nginx, change a socket permission, and raise a timeout simultaneously, the next successful request will not tell you which action solved the problem. Preserve the before-and-after status and log lines so the eventual fix is reproducible.
Common mistakes that make an outage last longer
- Restarting nginx first every time: if nginx is active and the backend is refusing connections, a restart does not repair the upstream.
- Treating every 503 as a crash: inspect for
limiting requestsand the zone name before changing application services. - Raising a timeout without measuring backend behavior: a longer wait can conceal a stuck worker and make the user experience worse.
- Reading only the bottom of
systemctl status: usejournalctlfor the complete record and the relevant time window. - Changing a directive in the wrong nginx block: confirm that the block matches the failing URL, especially when an override seems ineffective.
- Ignoring the operating-system policy layer: on RHEL-family hosts, check the SELinux boolean and related evidence before blaming nginx configuration.
- Assuming a listener proves health:
ss -tlnpshows that a process accepted the port or socket, not that it will return a complete, valid response. - Widening the investigation without timestamps: unrelated old warnings can distract from the event that produced the current status code.
Quick decision checklist
- 502 plus “connection refused”: check whether the backend is running and listening, then inspect its journal.
- 502 with an early upstream close: look for a backend crash, memory exhaustion, or malformed response.
- 503 plus “limiting requests”: investigate nginx’s rate or connection limit and the named zone.
- 504 after an otherwise successful upstream connection: measure the backend’s quiet interval and inspect the effective
proxy_read_timeout. - PHP application and no PHP-FPM process: repair or restart PHP-FPM, then verify the socket or port and permissions.
- RHEL-family host with a policy-related connection failure: inspect
getsebool httpd_can_network_connectand correlate it with the denial.
What this method does not establish by itself
These checks diagnose the nginx-to-backend path and the Linux services that operate it. They do not, on their own, prove that DNS, a TLS certificate, Apache configuration, file ownership, or disk capacity is correct. If nginx and the backend are healthy and the logs show no corresponding request, investigate the layer where the request is stopping rather than forcing an nginx status-code explanation.
Best Value
Frequently Asked Questions
What should I check first when a Linux website is down?
Run sudo systemctl status nginx and the status command for the backend, then read sudo journalctl -u nginx and the backend journal. Confirm the configured upstream is listening with ss -tlnp before changing nginx settings.
Does a 502 always mean nginx is broken?
No. A 502 means nginx could not obtain a valid upstream response. The backend may be stopped, listening on the wrong port or socket, inaccessible because of permissions or SELinux, crashing, or returning an invalid response while nginx itself remains healthy.
Recommended Free Tools
Why am I getting a 503 when the backend is running?
Nginx can intentionally return 503 when a rate or connection limit rejects traffic. Look for an error-log entry containing limiting requests, the client IP, and the zone name. That evidence points to nginx limiting rather than a dead backend.
How long does nginx wait before returning a 504?
The default proxy_read_timeout is 60 seconds. It limits the gap between successive reads from the upstream, not the total response duration. A streaming response can last longer than 60 seconds, while a silent upstream can time out at that interval.
Why did my proxy_read_timeout change not work?
Verify that the directive is in the nginx location block handling the failing URL. Nginx ticket #1471 reported an apparent override failure and a 45-second 504; the ticket was closed as invalid, with placement in the matching location identified as the workaround.
Should I disable SELinux to fix a 502?
Do not disable it merely because a 502 occurred. On RHEL-family systems, inspect getsebool httpd_can_network_connect and correlate the result with a policy denial involving the exact upstream connection. Change policy only when the evidence identifies it as the blocking layer.
The Bottom Line
Start with evidence, not guesses: inspect nginx and the backend with systemctl, read complete journals, match the nginx error log to the status code, and verify the upstream listener. Treat 502 as a failed or invalid upstream, 503 as potentially intentional limiting, and 504 as an upstream read delay. Restart only the failed component, place timeout changes in the matching location, and confirm every fix with fresh logs and a repeat request.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




