How to Set Up External Uptime Monitoring for Any Host

How to Set Up External Uptime Monitoring for Any Host

External uptime monitoring works because the check runs from a machine that is not your server, on a network path that is not your server's, and it fails when your server cannot answer. An internal check, whether it is a cron job, a plugin, or a status page widget running on the same box, can only report on a machine that is still alive enough to run the check. When the host's network drops, when the kernel panics, when the disk fills and the web server stops accepting connections, or when a firewall rule change locks out the world, the internal checker goes down with the thing it was supposed to watch. You get silence, and silence looks exactly like everything being fine.

That is the whole argument for external uptime monitoring in one paragraph. The rest of this article is about how to actually configure it, what the probe is doing on the wire, and how to make the alerts mean something.

What an External Check Actually Sends

Almost every external monitor is doing one of a small number of things: an HTTP or HTTPS request, a TCP connect, a ping, or a DNS query. The HTTP check is the one you want for a website, because it exercises the whole stack: DNS resolution, TCP handshake, TLS negotiation, the request itself, and the response. A ping only tells you the host is reachable at the IP layer, which is nearly useless for diagnosing a web application.

The simplest possible check is a request for a URL and an assertion about the status code. You can reproduce exactly what a monitor does from your own terminal with curl:

curl -sS -o /dev/null \
  -w 'code=%{http_code} dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n' \
  https://example.com/healthz

The output shape looks like this:

code=200 dns=0.004 connect=0.021 tls=0.048 total=0.213

Those four timings are the useful part. If dns climbs, your resolver or your authoritative nameservers are the problem. If connect climbs but dns is flat, you have a routing or saturation issue. If tls is slow, the handshake is expensive, which often means the server is under load or the certificate chain is being rebuilt on every connection. If total is slow while everything before it is fast, your application is the bottleneck and the network is innocent.

Choosing What to Probe, and From Where

Do not point the monitor at your home page. Point it at a dedicated endpoint that does the minimum work needed to prove the application is alive, and nothing more. A static file is a weak test because it can be served from cache or from a CDN edge that is still up while your origin is dead. A full page render is a strong test but a noisy one, because a slow database query will trip it and you will spend the evening chasing a false alarm.

A health endpoint that touches the things you actually depend on is the right middle ground. It should open a database connection, run a trivial query, and return a small body. Keep it unauthenticated but uninformative: return a status code and the word ok, not a version string, not a build hash, not a list of dependencies. Anything you print there is public.

On the monitor side, the setting that matters most is the number of probe locations. A single location gives you a single vantage point, and a single vantage point will occasionally be wrong: a peering dispute between that provider and your host, a route flap, a local outage at the probe. Two or three locations, configured to alert only when a majority fail, removes most of that noise. The tradeoff is that a real outage now has to be seen by more than one probe before you hear about it, which adds a little latency to the alert. That is usually the right trade.

Set the check interval to something you can actually act on. A one minute interval is fine for a small site. Going below that mostly buys you faster alerts about problems that resolve themselves before you finish reading the message.

Configuring the Check and the Alert

Most monitors let you assert on the response body, not just the status code. Use that. A reverse proxy that returns a friendly error page with a 200 status is a classic failure mode, and a status code check will happily report it as up. Assert on a short string you control:

GET /healthz HTTP/1.1
Host: example.com
User-Agent: uptime-probe/1.0
Accept: */*

HTTP/1.1 200 OK
Content-Type: text/plain
Cache-Control: no-store

ok

Two details in that exchange are worth copying into your config. First, the Cache-Control: no-store header on the health response, so no intermediary caches the result and serves a stale ok while your origin is down. Second, a distinctive User-Agent, so you can find probe traffic in your access logs and, if you want, allow it through a rate limiter that would otherwise block it.

If your monitor supports custom headers, send a shared secret and have the health endpoint check it. That keeps the endpoint from being a free target for anyone who guesses the path, and it lets you distinguish a real probe from random traffic when you are reading logs at two in the morning.

Then there is the alerting path, which is where most setups quietly fail. An alert that goes only to email is an alert you will miss. Route it to something that makes noise on a device you carry, and make sure the notification path does not depend on the infrastructure being monitored. If your alerting runs on the same host, or the same provider, or the same DNS zone as the site, you have rebuilt the internal checker with extra steps.

Making the Alerts Trustworthy

An external monitor is only as good as your willingness to act on it. Two settings do most of the work here. The first is confirmation: require the check to fail from more than one location, or to fail twice in a row, before firing. The second is recovery notification, so you know when the incident is over rather than discovering it by refreshing a dashboard.

Watch the false positive rate for the first few weeks and tune. If you are getting woken up for blips that resolve in under a minute, raise the confirmation threshold. If you are finding out about outages from your users, lower it. There is no universal correct value, only the one that matches how much downtime your site can tolerate and how much noise you can stand.

Finally, test the alert path deliberately. Take the site down on purpose, or point the monitor at a URL that returns 500, and confirm the notification arrives where you expect it. An untested alert is a guess.

What to Do Next

Pick one endpoint that proves your application is alive, add a no-store header to it, and point a monitor at it from at least two locations with a body assertion rather than a status code check. Send the alerts somewhere you will actually see them, on a path that does not share fate with the site. Run it for a month, look at what fired, and adjust the thresholds. The goal is not a green dashboard. The goal is that the first person to notice your site is down is you.

Related articles

Subscribe to our newsletter

Get the latest hosting tips, performance insights, and industry news.