Skip to content
ohsudo, Home

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?

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.

Start over

What does the browser say?

Start over

What does the warning say?

Click the warning, or "Advanced", to see its code.

Start over

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 it

Not this?Start over

What does the browser console say?

Press F12 and open the Console tab, then reload the page.

Start over

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.log
Read the fix: Nginx "502 Bad Gateway": find the cause in the error log

Not 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.log
Read the fix: Nginx "504 Gateway Time-out": find out what's slow before raising the timeout

Not 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, State
Read the fix: IIS "HTTP Error 500.19" and "503 Service Unavailable": read the code, then fix web.config or the app pool

Not 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.log
Read the fix: Nginx "403 Forbidden": read the error log, then fix the index, permissions or SELinux

Not 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_size
Read the fix: Nginx "413 Request Entity Too Large": raise the upload limit in the right place

Not 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 buffer

Not 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 AAAA

No 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 / httpd

Start over

Likely 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 443
Read the fix: "Connection timed out" vs "Connection refused": what each one tells you, and how to fix it

Not 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 -dates
Read the fix: "Certificate has expired": check the dates, renew it, and find out why it didn't renew

Not 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-run
Read the fix: Certbot "failed to authenticate some domains": read the Type, then fix DNS, port 80 or the path

Not 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-control
Read the fix: "Blocked by CORS policy": what the browser is really refusing, and how to fix it on the server

Not 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 host

Not 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 it

Not this?Start over

What does the start error say?

sudo journalctl -u nginx -n 30 --no-pager

Start over

Likely 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 -t
Read the fix: "Job for nginx.service failed because the control process exited with error code": how to find the cause

Not 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.

All troubleshooting guides →