Monitor your servers with Uptime Kuma
The first thing I put on any new server is a monitor that tells me when it's down. Uptime Kuma is a small web app that checks your sites, ports and servers on a schedule, and pings you on Telegram, email or whatever else you use when something stops answering. It also does public status pages.
This builds on the Docker and Caddy setup. If you don't have that running yet, start there. Not sure what else will share the box? The VPS size calculator helps you add it up.
Add it to your compose file
uptime-kuma:
image: louislam/uptime-kuma:1
restart: unless-stopped
mem_limit: 384m
volumes:
- kuma:/app/data
Add kuma: under volumes: at the bottom of the file. There's no ports: section on purpose. Only Caddy publishes ports, so Kuma is reachable through HTTPS and nowhere else. Check docker stats after a week and adjust the memory limit to what you actually see. If you'd rather assemble the file with a form, the compose generator can do it.
Add it to Caddy
status.example.com {
reverse_proxy uptime-kuma:3001
}
docker compose up -d docker compose exec -w /etc/caddy caddy caddy reload
Point a DNS record for status.example.com at your server first, or Caddy can't get a certificate. Caddy handles the WebSocket connection Kuma's dashboard uses without any extra config.
Create the admin account
Open https://status.example.com. The first screen asks you to create an admin user. Do it straight away: until you do, anyone who finds the URL could claim it. Use a long password from your password manager and turn on two-factor login under Settings, Security.
Your first monitors
Click Add New Monitor. Four types cover most of what you need:
- HTTP(s) for every site and web app you run. Set the interval to 60 seconds or more. Checking every 20 seconds on a small server just burns CPU for nothing.
- TCP Port for things that aren't websites, like SSH on port 22 or a database port you've deliberately exposed.
- Ping for the server itself. Useful, but a ping reply doesn't mean your apps are up, so don't rely on it alone.
- Push for jobs that run on a schedule. Kuma gives you a URL, and your script calls it when it succeeds. If the call stops arriving, you get an alert. That's the cheapest way to know your nightly restic backup is still running.
For a push monitor, add one line to the end of your backup script, using the URL Kuma shows you:
curl -fsS -m 10 "https://status.example.com/api/push/CHANGE_ME?status=up&msg=OK" > /dev/null
Set the monitor's heartbeat interval a bit longer than the job's schedule. Because the script runs with set -e, the line is only reached if every step before it worked.
Notifications
A monitor nobody hears about is a log file. Under Settings, Notifications, add at least one channel and use Test to confirm it arrives. Telegram, email (SMTP), Discord, Slack, ntfy and Gotify are all built in. Tick "Default enabled" so new monitors use it automatically, and "Apply on all existing monitors" to catch the ones you already made.
Under each monitor's settings you can raise Retries to 2 or 3. That way one dropped packet doesn't wake you at night, but a real outage still does.
A public status page
Go to Status Pages, New Status Page, pick a name and a slug, then add the monitors you want people to see. It's served at /status/your-slug. If you want it on its own domain, add the domain in the status page settings and give that domain its own block in the Caddyfile pointing at uptime-kuma:3001.
Only show monitors you're happy to make public. Hostnames and ports of internal services don't belong on a page anyone can read.
Who watches the watcher?
If the server is down, Kuma is down with it, and so is the alert. Run one monitor from somewhere else: a free external uptime service pointed at your Kuma URL, or a second Kuma on another small box watching the first. Without that, a dead server is silent.
Back it up
Everything Kuma knows is in an SQLite database inside the kuma volume. Losing it means re-creating every monitor by hand. Include the volume's data in your restic backups, using the SQLite .backup command from that post rather than copying the live file.
When to move on
Kuma is great for "is it up?" checks. If you want graphs of CPU, memory and disk over time, that's a different tool. Start with Kuma, and add metrics once you have something worth graphing. Running more than a handful of services on the same box? Compare plans on the VPS voucher page before you run out of RAM.