Setting Up Uptime Kuma: Self-Hosted Uptime Monitoring

Published

Uptime Kuma is a free, self-hosted uptime monitor with a clean web UI, 90+ notification integrations, and none of the per-monitor pricing that comes with hosted services like UptimeRobot’s paid tiers. It’s also one of the easiest self-hosted tools to get running badly — the most common mistake is storage-related, and it’ll bite you later rather than on day one. Here’s how to set it up correctly.

Search intent

Someone searching “uptime kuma setup” wants a working install (Docker, port, first monitor) plus the practical gotchas — not a feature tour.

Install with Docker

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    volumes:
      - ./uptime-kuma-data:/app/data
    ports:
      - "3001:3001"
    restart: unless-stopped

louislam/uptime-kuma:2 is the current recommended tag (the 2.x line, latest stable release 2.3.0 at the time of writing) — avoid pinning to :1 for a new install. Bring it up with:

docker compose up -d

Uptime Kuma listens on port 3001 by default. On first visit to http://<host>:3001, you’ll be prompted to create the admin account — do this immediately, since the setup wizard is open to anyone who reaches that port until an account exists.

The storage mistake that will corrupt your database

Uptime Kuma uses SQLite for its data store, and SQLite requires POSIX file locks to work correctly. Put the ./uptime-kuma-data volume on an NFS or CIFS/SMB network share and you are setting yourself up for database corruption — these network filesystems don’t reliably support the file locking SQLite depends on. This is documented behavior, not an edge case: use a local volume or block storage for the data directory. If you’re running this in a homelab with a NAS backing most of your container storage, this is the one container where that default doesn’t work — keep the data directory on local disk (or a local ZFS/LVM volume) instead.

Set up your first monitors

Uptime Kuma supports three check types most self-hosters actually need:

  • HTTP(s) — checks a URL returns an expected status code; use this for websites, dashboards, and any service with a web UI.
  • TCP port — checks whether a specific port accepts connections; use this for databases, SSH, or anything without an HTTP endpoint.
  • Ping (ICMP) — checks basic host reachability; use this for routers, switches, or anything you just need to know is powered on and networked.

Add a monitor from the dashboard, pick the check type, set the interval (defaults are fine for most homelab use — tighten to 20-30 seconds if you’re monitoring something latency-sensitive), and assign it to a notification target.

Notifications

Uptime Kuma supports 90+ notification services out of the box — Discord, Telegram, Slack, ntfy, Gotify, Pushover, Matrix, PagerDuty, and email (SMTP) among them. Configure at least one under Settings → Notifications before you need it; a monitoring tool that fails silently because no notification target was ever wired up defeats the purpose.

Run it somewhere separate from what it’s monitoring

Don’t run Uptime Kuma on the same host it’s supposed to be watching. If that host goes down, your monitor goes down with it and you get no alert at all — the one scenario a monitoring tool exists to catch. A small VM, a Raspberry Pi, or even a cheap cloud instance works; the point is independence from the infrastructure being monitored.

Bottom line

Docker install is genuinely five minutes of work — the setup that actually matters is keeping the SQLite data directory off NFS/CIFS, wiring up at least one notification target before you need it, and running the monitor itself somewhere independent of what it’s watching. Once up/down checks aren’t enough and you need real metrics (CPU, memory, disk I/O trends), see Prometheus/Grafana vs Netdata vs Zabbix for the next step up.