Troubleshooting guide
Website down? Find the cause, step by step
An error page, a certificate warning, or a site that never loads.
What happens when you open the site?
- An error page with a code502, 504, 503, 403, 413, 400…
- It never loads"This site can't be reached", "refused" or "timed out"
- A certificate or security warning"Your connection is not private"
- "Too many redirects"ERR_TOO_MANY_REDIRECTS
- The page loads, but its data or API doesn'tErrors in the browser console
Which code does the error page show?
It's in the page title, or in the browser's developer tools (F12 → Network), next to the request that failed.
What does the browser say?
What does the warning say?
Click the warning, or "Advanced", to see its code.
Likely cause
Two layers send the browser in circles
One part redirects to HTTPS (or to www) and another sends it back: often Cloudflare's Flexible SSL with a server that forces HTTPS, or a load balancer that talks HTTP to the app.
Check it
curl -sIL http://example.com | grep -iE '^(HTTP|location)'Read the fix: ERR_TOO_MANY_REDIRECTS with Nginx and Cloudflare: find the loop and break itNot this?Start over
What does the browser console say?
Press F12 and open the Console tab, then reload the page.
Likely cause
nginx gets no valid answer from your app
nginx itself works. The app behind it (Gunicorn, Node.js, PHP-FPM, a container) is down, listens on another port or socket, or crashes while answering. nginx's error log names the exact reason.
Check it
sudo tail -n 20 /var/log/nginx/error.logRead the fix: Nginx "502 Bad Gateway": find the cause in the error logNot this?Start over
Likely cause
Your app is too slow, or can't be reached
nginx passed the request on, waited (60 seconds by default) and gave up. The error log says whether connecting or reading timed out, which points to a firewall or to a slow app.
Check it
sudo tail -n 20 /var/log/nginx/error.logRead the fix: Nginx "504 Gateway Time-out": find out what's slow before raising the timeoutNot this?Start over
Likely cause
The application pool is stopped
IIS answers 503 when the site's application pool isn't running. If it stops again after a few requests, the app is crashing and Rapid-Fail Protection turned it off.
Check it
Get-ChildItem IIS:\AppPools | Select-Object Name, StateRead the fix: IIS "HTTP Error 500.19" and "503 Service Unavailable": read the code, then fix web.config or the app poolNot this?Start over
Likely cause
nginx refuses to serve the files
Usually there's no index file, nginx can't enter one of the folders on the path, or SELinux blocks it. The error log line says which.
Check it
sudo tail -n 20 /var/log/nginx/error.logRead the fix: Nginx "403 Forbidden": read the error log, then fix the index, permissions or SELinuxNot this?Start over
Likely cause
The upload is bigger than the limit
nginx refuses request bodies over client_max_body_size, 1 MB by default. Raise it where the request is handled, then check your app's own limit, which comes next.
Check it
sudo nginx -T | grep client_max_body_sizeRead the fix: Nginx "413 Request Entity Too Large": raise the upload limit in the right placeNot this?Start over
Likely cause
The browser sends headers or cookies that are too big
A cookie that grew too large is the usual cause. Clearing the site's cookies fixes it for you; large_client_header_buffers in nginx, or smaller cookies, fixes it for everyone.
Read the fix: Nginx "upstream sent too big header while reading response header": raise the right bufferNot this?Start over
Likely cause
The name doesn't point to your server
The browser couldn't turn the domain into an address. Check the A (and AAAA) records at your DNS provider: they must hold your server's public IP. A new or changed record can take a while to reach every resolver.
Check it
dig +short example.com A
dig +short example.com AAAANo article yet: the steps above are the fix.
Not this?Start over
Is the web server running?
sudo systemctl status nginx --no-pager # or apache2 / httpdLikely cause
A firewall drops the connection
Timed out means nothing answered at all: a firewall on the server, a cloud security group, or a network in between drops the packets. Test from outside with a short timeout.
Check it
nc -vz -w 5 example.com 443Read the fix: "Connection timed out" vs "Connection refused": what each one tells you, and how to fix itNot this?Start over
Likely cause
The certificate has expired
The server still sends an old certificate: the renewal didn't run, failed, or ran without the web server being reloaded. Check the dates it actually serves.
Check it
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -datesRead the fix: "Certificate has expired": check the dates, renew it, and find out why it didn't renewNot this?Start over
Likely cause
Let's Encrypt can't validate the domain
The error's Type (dns, connection, unauthorized, caa) tells you which check failed: the DNS record, port 80, the challenge file, or a CAA record.
Check it
sudo certbot renew --dry-runRead the fix: Certbot "failed to authenticate some domains": read the Type, then fix DNS, port 80 or the pathNot this?Start over
Likely cause
The API doesn't allow your site's origin
The browser blocks the answer because the API doesn't send Access-Control-Allow-Origin for your site. Fix it on the API side, not in the browser.
Check it
curl -sI -H 'Origin: https://app.example.com' https://api.example.com/ | grep -i access-controlRead the fix: "Blocked by CORS policy": what the browser is really refusing, and how to fix it on the serverNot this?Start over
Likely cause
localhost inside a container is the container itself
An app in a container that connects to localhost reaches itself, not your database or another container. Use the other service's name, or host.docker.internal for the host.
Read the fix: Docker: "connection refused" to localhost from a container — how to reach the hostNot this?Start over
Likely cause
Nothing listens on that port and address
The server answered "no" at once: the web server listens on another port, only on 127.0.0.1, or not on IPv6, or a firewall rejects the connection.
Check it
sudo ss -tlnp | grep -E ':(80|443)\b'Read the fix: "Connection timed out" vs "Connection refused": what each one tells you, and how to fix itNot this?Start over
What does the start error say?
sudo journalctl -u nginx -n 30 --no-pagerLikely cause
Another program holds port 80 or 443
Apache, a second nginx, a container publishing the port or a leftover process got there first. Find it, then stop it or move one of them.
Check it
sudo ss -tlnp 'sport = :80'Read the fix: "Address already in use": find who is using port 80 (or any port)Not this?Start over
Likely cause
The web server fails at start-up
Most often a configuration error, a missing certificate file or a permission. The journal shows the real reason, and nginx -t checks the configuration.
Check it
sudo nginx -tRead the fix: "Job for nginx.service failed because the control process exited with error code": how to find the causeNot this?Start over
Have an exact error message? Paste it into search instead.
Every cause this guide covers
The same answers, all on one page, if you would rather scan them.
- Two layers send the browser in circlesERR_TOO_MANY_REDIRECTS with Nginx and Cloudflare: find the loop and break it
- nginx gets no valid answer from your appNginx "502 Bad Gateway": find the cause in the error log
- Your app is too slow, or can't be reachedNginx "504 Gateway Time-out": find out what's slow before raising the timeout
- The application pool is stoppedIIS "HTTP Error 500.19" and "503 Service Unavailable": read the code, then fix web.config or the app pool
- nginx refuses to serve the filesNginx "403 Forbidden": read the error log, then fix the index, permissions or SELinux
- The upload is bigger than the limitNginx "413 Request Entity Too Large": raise the upload limit in the right place
- The browser sends headers or cookies that are too bigNginx "upstream sent too big header while reading response header": raise the right buffer
- The name doesn't point to your server
- A firewall drops the connection"Connection timed out" vs "Connection refused": what each one tells you, and how to fix it
- The certificate has expired"Certificate has expired": check the dates, renew it, and find out why it didn't renew
- Let's Encrypt can't validate the domainCertbot "failed to authenticate some domains": read the Type, then fix DNS, port 80 or the path
- The API doesn't allow your site's origin"Blocked by CORS policy": what the browser is really refusing, and how to fix it on the server
- localhost inside a container is the container itselfDocker: "connection refused" to localhost from a container — how to reach the host
- Nothing listens on that port and address"Connection timed out" vs "Connection refused": what each one tells you, and how to fix it
- Another program holds port 80 or 443"Address already in use": find who is using port 80 (or any port)
- The web server fails at start-up"Job for nginx.service failed because the control process exited with error code": how to find the cause