Server Uptime Monitoring: What to Check and How to Set It Up
Server uptime monitoring answers one question - can people use what runs on this server right now? - and, done well, a second one: will they still be able to in an hour? The first needs checks from outside the server. The second needs a look inside it.
The Two Halves of Uptime Monitoring
| External checks | Internal checks | |
|---|---|---|
| Runs from | Another network or several locations | The server itself |
| Detects | Server or site unreachable, wrong response, expired SSL, broken DNS | Full disk, memory pressure, stopped services, failed cron jobs, high load |
| Works when the server is dead | Yes | No - a dead server reports nothing |
| Warns before the outage | Rarely | Often hours ahead |
You need both. External checks are the source of truth for "is it down"; internal checks explain why and catch most problems before they become an outage.
External Checks
1. HTTP(S) check
Request a URL and check the status code - ideally a page that touches the application and database, not a static file:
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' --max-time 10 https://example.com/health
Alert on non-2xx codes, timeouts, and response time well above normal.
2. Keyword check
A page can return 200 OK and still show "Database connection error". Check for a word that only appears when the page renders correctly:
curl -s --max-time 10 https://example.com/ | grep -q 'Add to cart' || echo "keyword missing"
3. Port check
For services without HTTP - SSH, databases exposed to an app server, mail, game servers:
nc -z -w 5 db.example.com 5432 && echo open || echo closed
4. Ping (ICMP)
Tells you the host's network stack answers - nothing about the services on it. Useful as a supporting signal, never as the only check; many providers also block ICMP.
5. SSL certificate and domain expiry
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
Alert 14-21 days before expiry. A failed Let's Encrypt renewal is one of the most common fully preventable outages.
6. DNS
Check that the domain resolves to the expected IP from public resolvers - a changed or expired DNS record takes everything down while the server itself is perfectly healthy:
dig +short example.com @1.1.1.1
Internal Checks (Linux)
These are the signals that announce outages in advance. On any Linux server - Ubuntu, Debian, Rocky, Alma - the commands are the same:
| What | Command | Alert when |
|---|---|---|
| Disk space | df -h --output=target,pcent |
Any filesystem above 85-90% |
| Inodes | df -i |
Above 90% (disk "full" with free space) |
| Memory | free -m |
Available memory below 10%, swap growing |
| Load | uptime / cat /proc/loadavg |
15-min load above CPU count for a sustained period |
| Critical services | systemctl is-active nginx mysql |
Anything other than active |
| Failed units | systemctl --failed --no-legend |
Any output |
| Reboots | uptime -s |
Boot time changed unexpectedly |
| OOM kills | journalctl -k --since "1 hour ago" | grep -i oom |
Any match |
| Backups / cron | Age of the last backup file, cron log | Older than expected |
A compact check you can run from cron or any monitoring tool - it prints nothing when the server is healthy:
#!/bin/sh
df -P | awk 'NR>1 && $5+0 > 90 {print "disk " $6 " " $5}'
free | awk '/Mem:/ && $7/$2 < 0.10 {print "memory available " int($7/$2*100) "%"}'
for s in nginx mysql; do systemctl is-active --quiet "$s" || echo "service $s not running"; done
systemctl --failed --no-legend --plain | awk '{print "failed unit " $1}'
Details for each signal: service status, uptime and load average, list all cron jobs.
Step-by-Step Setup
- List what users depend on. Website, API, admin panel, mail, database for other servers. Each gets an external check.
- Add an HTTP check with a keyword for every site, at a 1-5 minute interval, from at least two locations.
- Add SSL expiry and DNS checks for every domain.
- Add port checks for non-HTTP services that other systems rely on.
- Install internal monitoring for disk, memory, load and critical services, and add checks for backups and important cron jobs.
- Set alert rules: require two consecutive failures (or two locations) before alerting, send a recovery notice, and route critical alerts to a channel you see at night.
- Test it. Stop a service, block a port with the firewall, fill a test filesystem. An alert you have never seen fire is an alert you cannot trust.
- Plan maintenance. Pause alerts during planned work instead of ignoring them - see maintenance windows and uptime.
Intervals and Alert Rules
| Service | Check interval | Alert after |
|---|---|---|
| Shop, payments, API with SLA | 1 min | 2 failures from 2 locations |
| Company website, client sites | 1-5 min | 2 failures |
| Internal tools | 5 min | 3 failures |
| SSL / domain expiry | daily | 21 and 7 days before |
| Disk, memory, services | 1-5 min | threshold held for 5-10 min |
| Backups, cron jobs | per job | missed run |
Avoid alerting on single failures: a dropped packet between the probe and your server is not an outage, and an alert channel full of false alarms gets muted.
Uptime Percentages in Practice
| Uptime | Downtime per month | Downtime per year |
|---|---|---|
| 99% | 7 h 18 min | 3 d 15 h |
| 99.5% | 3 h 39 min | 1 d 19 h |
| 99.9% | 43 min | 8 h 46 min |
| 99.95% | 22 min | 4 h 23 min |
| 99.99% | 4 min 23 s | 52 min |
With a 5-minute check interval you cannot reliably measure anything above 99.9% - a 4-minute outage may never be seen.
Common Mistakes
- Monitoring from the same server. A script on the server cannot report that the server is down.
- Checking only the homepage. Cached homepages keep answering while checkout, login or the API are broken.
- Ping as the only check. The host answers ICMP while nginx is stopped.
- No internal monitoring. Most outages on small servers are a full disk, an expired certificate or a stopped service - all visible in advance.
- Alerts to an inbox nobody reads at night.
Tools
Free options are compared in free server uptime monitoring tools. In short: UptimeRobot and Uptime Kuma for external checks only; HetrixTools and Zuzia for external checks plus metrics from the server.
Zuzia combines both halves in one panel: website, SSL, port and DNS checks from three locations (Poland, New York, Singapore), CPU, RAM, disk and load from the server, and scheduled tasks - like the check script above - that run on the server with the output of every run kept and summarised by AI. Alerts go by email, Slack, SMS or phone call. The free plan covers one server; paid plans start at $9/month for 10.
FAQ
What is server uptime monitoring?
Regularly checking that a server and the services on it answer - from outside (HTTP, port, ping, SSL, DNS) and, ideally, also from inside (disk, memory, services, scheduled jobs) - and alerting when they do not.
How often should I check server uptime?
Every 1-5 minutes for anything public, every minute for services that take payments or have an SLA. Internal metrics such as disk space every 1-5 minutes as well.
Is ping enough to monitor a server?
No. Ping only shows that the network stack answers. The web server, database or application can be down while ping succeeds.
How do I monitor uptime of an Ubuntu server?
The same way as any Linux server: an external HTTP or port check for each service, plus internal checks of df, free, systemctl is-active and systemctl --failed. Nothing Ubuntu-specific is required.
Can I monitor a server behind a firewall or NAT?
External checks need a reachable endpoint. For private servers, use internal monitoring that pushes results out (an agent or a heartbeat), so the server reports in and you are alerted when it stops reporting.
What is the difference between uptime and availability?
Uptime is the time a server is running. Availability is the time users can actually use the service. A server can be up while the service is unavailable - which is why HTTP and keyword checks matter more than ping or uptime.