"Site Not Loading" — a calm triage

The most common ticket, and the most panic-inducing. Don't guess. Walk down this ladder from the outside in, and the problem will show itself — usually within a couple of minutes.

The golden rule

Work from the outside in: DNS → reach the server → server is up → app is running → SSL. Don't skip ahead. Each rung tells you whether the problem is above or below it.

First: is it down for everyone, or just them?

Before anything technical, rule out the customer's own network. Ask them to try mobile data instead of wifi, or check the site from a "down for everyone or just me" service. If it works for you but not them, it's their side (their ISP, their router, their browser cache, or a hosts-file entry) — not the server.

Rung 1 — Does the name resolve? (DNS)

dig +short thedomain.com
  • Nothing / wrong IP? DNS is the problem. The record is missing, wrong, edited in the wrong place, or still propagating. Go to the DNS and Point a Domain pages.
  • Correct server IP? DNS is fine — move down to Rung 2.

Rung 2 — Can you reach the server at all?

# Is the box even alive?
ping thedomain.com

# Is the web port open?
nc -zv thedomain.com 443
nc -zv thedomain.com 80
  • Ping works, ports refused/timeout? The server is up but the web server isn't listening, or a firewall is blocking. Rung 3.
  • Nothing responds at all? The server may be off, crashed, or the whole IP is firewalled. Check the hosting panel — is the VPS actually running?
Ping failing isn't proof the site is down

Lots of servers block ping (ICMP) on purpose while still serving web traffic fine. Trust the nc port check on 80/443 more than ping.

Rung 3 — Is the web server running and listening?

SSH into the box and check:

# What's listening on the web ports?
sudo ss -tlnp | grep -E ':80|:443'

# Is nginx/apache actually running?
sudo systemctl status nginx     # or apache2

# If it's dead, the logs say why
sudo journalctl -u nginx --no-pager -n 50
sudo tail -n 50 /var/log/nginx/error.log
  • Nothing listening on 80/443? The web server is stopped or crashed. Start it (sudo systemctl restart nginx) and read the logs for why it died — usually a bad config edit. Test the config first: sudo nginx -t.
  • Listening only on 127.0.0.1? The app is bound to localhost, so the outside world can't reach it. It must listen on 0.0.0.0. Common with Node/Python apps behind a reverse proxy.

Rung 4 — Is the firewall in the way?

Two firewalls to check — the one on the server, and the cloud provider's.

# On the server
sudo ufw status            # ports 80, 443 should be ALLOW
# or
sudo iptables -L -n

Then check the cloud firewall / security group in the hosting panel (DigitalOcean firewall, AWS security group, etc.) — it must allow inbound 80 and 443. This is a very common miss: the server is perfect, but the cloud firewall never allowed the ports.

Rung 5 — App is up but throwing errors

If the page loads but shows 502, 503, or 504, the web server is reachable but the app behind it isn't answering:

CodeMeansCheck
502 Bad GatewayReverse proxy can't reach the appIs the app process running? Right port in the proxy config?
503 Service UnavailableApp is up but refusing (overloaded, restarting, maintenance)App logs, resource usage
504 Gateway TimeoutApp took too long to respondSlow query, stuck process, upstream timeout
500 Internal Server ErrorThe app itself crashed on this requestApplication logs

Rung 6 — HTTPS-specific problems

Loads on http:// but not https://, or shows a cert warning? That's SSL, not connectivity. Jump to Add an SSL Certificate — usually an expired cert, a name mismatch, or a Cloudflare redirect loop.

The one-screen decision tree

Follow the arrows
dig +short domain wrong / empty → fix DNS correct IP → nc port check refused → web server / firewall open → curl the site 5xx → app logs cert warning → SSL page 200 OK 🎉

Key takeaways

  • Triage from the outside in — never jump straight to the app.
  • digncss/systemctl → firewall → app logs → SSL.
  • Check both firewalls: the server's and the cloud provider's.
  • App bound to 127.0.0.1 is invisible from outside — needs 0.0.0.0.
  • 5xx = the app; cert warning = SSL; wrong IP = DNS. Let the symptom point you.