NGINX 502 Bad Gateway: Trace the Request Before Changing Timeouts
Trace a failing route through public HTTPS, NGINX, and the app to narrow down a 502 without exposing the upstream port.
RB
Suppose your status page is green, but opening a report returns a 502. Your app is behind NGINX on a small VM, and there’s a managed HTTPS proxy in front of it. You have three places to look and one error page that can’t tell you where to start.
Start with one failing read-only route. Request it through the public hostname, then from inside the VM through NGINX, then directly against the app if the app accepts HTTP. Compare the response and logs at each hop. HTTP Semantics defines 502 as a gateway or proxy receiving an invalid response from an upstream server. With more than one gateway, the public status alone doesn’t identify which one hit trouble.
Repeat the failing request from three places
This example assumes the public HTTPS endpoint forwards to an HTTP NGINX listener on port 8080, and NGINX forwards to an HTTP app on port 3000. Use your actual ports and upstream path. The two local commands run inside the VM. If NGINX is in a container, run the upstream probe from its network context and use the actual upstream address. Localhost inside a container points to that container.
curl -sS -i --max-time 10 https://reports.example.com/reports/latest
# Inside the VM, through the NGINX listener
curl -sS -i --max-time 10 -H 'Host: reports.example.com' \
http://127.0.0.1:8080/reports/latest
# From NGINX's network context, directly to the example app
curl -sS -i --max-time 10 http://127.0.0.1:3000/reports/latestThe curl manual covers the header and timeout options. The local Host header helps select the intended virtual host. For an HTTPS listener, use the correct hostname and certificate validation for the local probe too. Match the method, path and expected host where it matters. NGINX can rewrite the path and change the upstream Host header, so read the matching location and proxy settings before interpreting the direct-app result. Use a safe staging credential if needed and keep secrets out of shared output.
Use the first split to choose what to inspect
Public fails, local NGINX works. Look for the public request in NGINX logs if logging covers that route. If it’s missing, check the ingress destination port and the listener address. A proxy listening on loopback can answer your local command while remaining unreachable at the VM’s private address. If the request does appear, compare the effective path and headers. A successful local call only proves the local path you exercised.
Local NGINX fails, direct app works. Compare NGINX’s error log with the upstream address, port, scheme and route you just tested. A successful request from the VM shell doesn’t prove the same target is reachable from the proxy container. The NGINX upstream variables can show which addresses were tried and their response status. A logged upstream status of 502 can also mean NGINX couldn’t select a server, so read the error log alongside it.
The direct app call also fails. Check whether the process is listening at the expected address, then inspect its logs for that route. A refused connection and a valid application error response are different observations. If all three calls work, repeat the original read-only request under the same conditions and compare timestamps rather than assuming the problem is gone.
For a Cube custom domain, the Krova custom domains guide explains how to point the domain at the service port. Keep the app port private during this check. Once you’ve isolated the failing hop, repeat the original public request and a second read-only route that exercises the same service. You’ll have a specific observation to compare after the fix.
This guide was prepared with AI assistance from the linked documentation. The reports service and ports are hypothetical.
Rehearse the request path on a Cube
Use a self-managed Linux Cube to stage an NGINX proxy and app before changing a live route.




