Uptime Kuma Docker Compose Setup for Homelab 2026: Monitor Every Service

Reading time: ~14 minutes Audience: Homelab owners who want to know when their services go down — before their family tells them


Introduction: The “Who Watches the Watcher” Problem

Your homelab runs twenty Docker containers. Nextcloud holds your family photos. Jellyfin streams your media library. Pi-hole filters your DNS. Home Assistant controls your lights. And at 2 AM, while you are asleep, one of them silently crashes — and you find out at breakfast when your partner asks why the media server is broken again.

This is the fundamental monitoring problem every homelab owner faces: you cannot fix what you do not know is broken.

Uptime Kuma is the solution. It is a free, open-source, self-hosted uptime monitoring tool with a beautiful web dashboard, multi-channel notifications, public status pages, and support for HTTP, TCP, DNS, Ping, Docker, and Push monitors. It runs in a single Docker container, consumes under 100 MB of RAM, and can monitor fifty services from a Raspberry Pi. And in 2026, with version 1.x mature and feature-complete, it is the undisputed king of self-hosted uptime monitoring.

But deploying Uptime Kuma is only half the battle. The real question is: who watches the watcher? If Uptime Kuma itself goes down — because your Docker host rebooted, your Proxmox node crashed, or your ISP dropped the connection — all your monitoring goes dark and you will never know. This guide covers that too, with the Healthchecks.io “watch the watcher” pattern that gives you a dead man’s switch for your monitoring stack.

By the end of this guide, you will have: a production-ready Uptime Kuma deployment via Docker Compose, five real monitors watching your actual homelab services, Telegram and Discord notifications, a public-facing status page behind your reverse proxy, and a Healthchecks.io heartbeat that alerts you if Uptime Kuma itself dies. No other guide covers all of this in 2026.

New to Docker Compose? Start with our Docker Compose for Beginners guide. Already running a reverse proxy? Everything here integrates with Nginx Proxy Manager and Traefik.


Why Uptime Kuma in a Homelab?

Before you deploy anything, it helps to understand what Uptime Kuma is — and what it is not. The homelab monitoring landscape has several tools, and choosing the wrong one wastes hours.

Uptime Kuma vs. the Alternatives

Feature Uptime Kuma UptimeRobot (Free) Prometheus + Alertmanager Grafana OnCall
Self-hosted ✅ Yes ❌ SaaS only ✅ Yes ✅ Yes
Setup time ~10 minutes ~5 minutes ~2 hours ~1 hour
Status pages ✅ Built-in ✅ Built-in ❌ Needs Grafana ❌ No
Push monitors ✅ Yes ❌ No ✅ Pushgateway ✅ Yes
Docker monitoring ✅ Native ❌ No ✅ cAdvisor ❌ No
GUI dashboard ✅ Beautiful ✅ Simple CLI/config only ✅ Grafana
Notification channels 60+ 5 (free tier) 10+ 10+
Resource usage ~80 MB RAM N/A (SaaS) ~2 GB RAM ~500 MB RAM
Learning curve Low Low High Medium

When to choose Uptime Kuma: You want a dead-simple, beautiful uptime dashboard that takes 10 minutes to deploy and immediately tells you which services are up or down. You need built-in status pages, push monitors for cron jobs, and dozens of notification channels — without writing a single line of PromQL.

When to pair it with Prometheus and Grafana: Uptime is a binary signal — up or down. It does not tell you why your service is slow, which database query is eating CPU, or when your disk will fill up. For that, you want metrics. The two tools complement each other perfectly: Uptime Kuma for “is it alive?” and Grafana + Prometheus for “how healthy is it?”

Resource requirements: Uptime Kuma runs comfortably on a Raspberry Pi 4, an Intel N100 mini PC, or any Docker host with 512 MB of free RAM. The database (SQLite) stays small — under 200 MB even with hundreds of monitors and months of history.


What You’ll Need

Hardware Requirements

Component Minimum Recommended
CPU 1 core (ARM or x86) 2 cores
RAM 256 MB free 512 MB free
Disk 500 MB 2 GB (for history)
Network Any Dedicated VLAN for monitoring traffic

Software Prerequisites

  • Docker Engine 24.x+ and Docker Compose v2+
  • A Linux host — any distribution that runs Docker (Debian 12, Ubuntu 24.04, Proxmox LXC, Raspberry Pi OS)
  • Optional but recommended: a reverse proxy (Nginx Proxy Manager or Traefik) for HTTPS access
  • Optional: a Cloudflare Tunnel if you want to expose your status page publicly without opening ports

Services You Will Monitor

This guide assumes you have at least five homelab services running. Examples used throughout:

  1. NextcloudHTTP monitor on port 8443
  2. JellyfinHTTP monitor on port 8096
  3. Pi-holeDNS monitor on port 53
  4. PortainerHTTP monitor on port 9443
  5. Home AssistantHTTP monitor on port 8123

If you do not have these specific services, the monitor types and configuration patterns apply to any service in your stack.


Project Structure

Create a clean directory for Uptime Kuma. Keeping it alongside your other Docker Compose stacks makes backups straightforward.

~/docker/uptime-kuma/
├── docker-compose.yml
├── .env
└── data/          (auto-created by Docker)

The data/ directory holds the SQLite database, uploaded monitor screenshots, and notification credentials. Back this up.


The Docker Compose Configuration

docker-compose.yml

This is the production-ready Compose file. It pins the Uptime Kuma version (not latest), mounts a persistent volume, sets resource limits, and includes a healthcheck so Docker itself knows whether the container is healthy.

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - ./data:/app/data
    environment:
      - TZ=${TZ:-Asia/Jakarta}
    healthcheck:
      test: ["CMD", "extra/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 128M
    # Uncomment if you use a shared Docker network for reverse proxy
    # networks:
    #   - proxy_network

# Uncomment if using a shared reverse proxy network
# networks:
#   proxy_network:
#     external: true

Why version 1 and not latest? Pinning to the major version (1) means you get patch updates (1.23.x) automatically without risking a breaking v2 migration. When Uptime Kuma v2 is released, you will evaluate the changelog before upgrading — not wake up to a broken monitoring stack.

.env File

# Uptime Kuma
TZ=Asia/Jakarta

Keep it simple. The timezone ensures all timestamps, maintenance windows, and notification schedules align with your local time.

Optional: Docker Socket for Container Monitoring

If you want Uptime Kuma to monitor Docker containers directly (checking container health status from the Docker daemon), mount the Docker socket as read-only:

    volumes:
      - ./data:/app/data
      - /var/run/docker.sock:/var/run/docker.sock:ro

Security note: Mounting the Docker socket gives the container access to the Docker API. In a homelab this is generally acceptable, but understand the trade-off: any process with access to docker.sock can start, stop, or inspect any container on the host.


Step-by-Step Installation

Step 1: Create the Project Directory and Files

mkdir -p ~/docker/uptime-kuma
cd ~/docker/uptime-kuma

# Create the .env file
echo "TZ=Asia/Jakarta" > .env

# Create docker-compose.yml with the content above
nano docker-compose.yml

Step 2: Start the Container

docker compose up -d

Verify it is running:

docker compose ps
# Should show uptime-kuma as "Up" and "(healthy)"

Step 3: Complete First-Run Setup

Open http://<your-server-ip>:3001 in your browser. The first-run wizard asks you to:

  1. Create an admin account — username, password (use a password manager — you will not log in often, but losing this account means losing access to your monitoring dashboard)
  2. Enable 2FA (optional but recommended if your dashboard is accessible outside your LAN) — Uptime Kuma supports TOTP-based two-factor authentication
  3. Set a custom page title — call it “Homelab Status” or your domain name

Missing your server IP? If you deployed on Proxmox, use the container/LXC IP. If on bare metal, use ip addr show to find it.

Step 4: Add Your First Monitor

Click “Add New Monitor” and fill in:

Field Example Value Notes
Monitor Type HTTP(s) Most homelab services use HTTP
Friendly Name Nextcloud Display name on your dashboard
URL https://nextcloud.homelab.local Full URL, including https://
Heartbeat Interval 60 seconds 60s is fine for most services
Retries 3 Avoids false positives from transient blips
Resend Notification 0 (every down event) You want to know every time it goes down
Max Redirects 0 Most homelab services should not redirect
Accepted Status Codes 200 Optional; tighten to expected codes

Click Save. The monitor appears on your dashboard. It runs its first check within 60 seconds. A green heart means your service is reachable. A red heart means it is not — and if you have configured notifications, you will know immediately.

Step 5: Configure Notification Channels

A monitor without an alert is a log entry you will never read. Uptime Kuma supports over 60 notification channels. Here are the four most useful for homelab owners:

Channel Best For Setup Complexity
Telegram Instant push notifications to your phone Low — needs bot token + chat ID
Discord Sharing alerts with a homelab community or family server Low — needs webhook URL
Email (SMTP) Reliable fallback when chat services are down Medium — needs SMTP server credentials
ntfy Self-hosted push notifications, zero reliance on third parties Medium — needs ntfy server URL + topic

Setting up Telegram:

  1. Message @BotFather on Telegram and create a bot with /newbot
  2. Copy the bot token (looks like 123456:ABC-DEF1234ghikl...)
  3. Send a message to your bot, then visit https://api.telegram.org/bot<TOKEN>/getUpdates to find your chat ID
  4. In Uptime Kuma: Settings → Notifications → Setup Notification → Telegram
  5. Paste the bot token and chat ID, click Test, and confirm you receive the test message

Setting up Discord:

  1. In your Discord server: Server Settings → Integrations → Webhooks → New Webhook
  2. Copy the webhook URL (looks like https://discord.com/api/webhooks/...)
  3. In Uptime Kuma: Settings → Notifications → Setup Notification → Discord
  4. Paste the webhook URL, click Test

Step 6: Create a Public Status Page

A public status page lets your family (or users, if you share services) check the health of your homelab without accessing the admin dashboard. It is a read-only, beautifully branded page you can host at status.yourdomain.com.

  1. Settings → Status Page → New Status Page
  2. Give it a name and a slug (e.g., homelab)
  3. Pick which monitors appear — select the services your family cares about (Jellyfin, Home Assistant) but not internal-only ones (database, Docker socket)
  4. Customize the footer with your domain, a logo, and a custom message (“Having trouble? Message me on Signal.”)
  5. Copy the generated URL slug. If reverse proxy is configured, this becomes https://status.yourdomain.com

No reverse proxy yet? The status page URL will be http://<server-ip>:3001/status/homelab. Jump to the Reverse Proxy Integration section to make it accessible at a clean domain with HTTPS.

Step 7: Add Maintenance Windows

When you take Jellyfin down to add a new hard drive, you do not want Uptime Kuma spamming notifications. Maintenance windows suppress alerts on a schedule.

Settings → Maintenance → Add Maintenance Window, select the affected monitors, set the start/end time, and save. Notifications pause during the window but uptime checks continue — so you can see the downtime in your history without the noise.


Monitor Types & Decision Matrix

Uptime Kuma supports eight monitor types. Choosing the right one for each service is the difference between meaningful alerts and noise.

Monitor Type Protocol Best For Example
HTTP(s) HTTP/HTTPS GET Web services, APIs, dashboards Nextcloud, Portainer, Jellyfin
TCP Raw TCP connect Databases, game servers, mail servers MySQL (3306), Minecraft (25565), SMTP (25)
Ping ICMP Echo Network devices, bare-metal servers Router (192.168.1.1), NAS, managed switch
DNS DNS query DNS servers, ad-blockers Pi-hole (query google.com against 192.168.1.2:53)
Docker Docker socket API Container health checks Any container with a healthcheck defined in its Compose file
Push Inbound HTTP (passive) Cron jobs, backup scripts Nightly borg backup script pushes a heartbeat when it completes
MQTT MQTT topic IoT devices, sensor data Temperature sensor publishes to homelab/sensors/temp
gRPC gRPC health check Microservices Custom gRPC health probe endpoints

Decision Matrix: Which Monitor for Which Service?

Your Service Use This Monitor Why
Web app (Nextcloud, Jellyfin, Portainer, Home Assistant) HTTP(s) Verifies the web server responds with the expected status code
Database (PostgreSQL, MySQL, Redis) TCP Confirms the port is open and accepting connections without needing to authenticate
Router, switch, access point Ping Simplest network-layer check — does the device respond to ICMP?
Pi-hole, AdGuard Home, Unbound DNS Verifies DNS resolution works, not just that port 53 is open
Docker container with healthcheck Docker Reads container health status directly from Docker daemon — more accurate than a port check
Nightly backup script, log rotation cron Push The script calls a unique Uptime Kuma URL after success; if the URL is not called within the window, Uptime Kuma alerts
MQTT sensor (Zigbee2MQTT, ESPHome) MQTT Watches for a heartbeat message on a topic

Reverse Proxy Integration

Accessing Uptime Kuma on http://192.168.1.50:3001 works — until your browser marks it “Not Secure” and refuses to save your password. A reverse proxy gives you https://uptime.yourdomain.com with automatic SSL.

Option 1: Nginx Proxy Manager

If you already use Nginx Proxy Manager, this takes 30 seconds:

  1. Log into NPM at https://npm.yourdomain.com:81
  2. Hosts → Proxy Hosts → Add Proxy Host
  3. Fill in:
  4. Domain Names: uptime.yourdomain.com
  5. Forward Hostname / IP: uptime-kuma (the container name, if on the same Docker network) or 192.168.1.50
  6. Forward Port: 3001
  7. Websocket Support: ✅ Enable (Uptime Kuma uses WebSockets for real-time dashboard updates)
  8. SSL tab → select “Request a new SSL Certificate,” check “Force SSL” and “HTTP/2 Support”
  9. Click Save

Your dashboard is now at https://uptime.yourdomain.com with a valid Let’s Encrypt certificate.

For the status page, add a second proxy host: status.yourdomain.com → same backend (uptime-kuma:3001). In Uptime Kuma, configure the status page slug to homelab. Visitors to https://status.yourdomain.com see a dedicated read-only status page.

Option 2: Traefik

If you use Traefik, add these labels to your docker-compose.yml:

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.uptimekuma.rule=Host(`uptime.yourdomain.com`)"
      - "traefik.http.routers.uptimekuma.entrypoints=websecure"
      - "traefik.http.routers.uptimekuma.tls.certresolver=letsencrypt"
      - "traefik.http.services.uptimekuma.loadbalancer.server.port=3001"

The dashboard appears at https://uptime.yourdomain.com with automatic TLS.

Option 3: Cloudflare Tunnel (Zero Port Forwarding)

If you do not want to open any ports on your router, use a Cloudflare Tunnel to expose the status page publicly. Add this ingress rule to your config.yml:

ingress:
  - hostname: status.yourdomain.com
    service: http://uptime-kuma:3001
  - service: http_status:404

Security tip: Only expose the status page (status.yourdomain.com), not the admin dashboard (uptime.yourdomain.com). Add a Cloudflare Access policy to the admin dashboard subdomain for an extra authentication layer.


Watch the Watcher” — Healthchecks.io Integration

Here is the problem with self-hosted monitoring: when your Docker host crashes, Uptime Kuma crashes with it. You get no alert because the tool that sends alerts is also dead. This is the “who watches the watcher” problem, and the solution is a dead man’s switch.

Healthchecks.io is a free service (open-source, self-hostable) that expects a periodic HTTP request — a heartbeat — from your monitored service. If the heartbeat does not arrive within a configured grace period, Healthchecks.io sends you an alert. It works even when your entire homelab is offline because Healthchecks.io runs outside your infrastructure.

Setup (5 Minutes)

  1. Create a free Healthchecks.io account at healthchecks.io — the free tier includes 20 checks
  2. Create a new check → name it “Uptime Kuma Heartbeat,” set grace period to 5 minutes, set schedule to “/5 * * * ” (every 5 minutes)
  3. Copy the Ping URL — it looks like https://hc-ping.com/<uuid>

The Heartbeat Cron Job

On a secondary device — a VPS, a Raspberry Pi Zero, or even your always-on desktop — create a cron job that hits the Uptime Kuma health endpoint:

# Run every 5 minutes — verifies Uptime Kuma is responding
*/5 * * * * curl -s -o /dev/null -w "%{http_code}" https://uptime.yourdomain.com/api/status-page/heartbeat/homelab | grep -q "200" && curl -fsS -o /dev/null https://hc-ping.com/<uuid>

What this does:

  1. Every 5 minutes, the cron job hits your Uptime Kuma status page API
  2. If the response is HTTP 200 (Uptime Kuma is alive), it pings Healthchecks.io
  3. If the response is anything else (Uptime Kuma is down or unreachable), Healthchecks.io receives no ping
  4. Healthchecks.io waits the 5-minute grace period, then sends you an alert via email, Telegram, Discord, or any of its dozen notification channels

The key is running this cron job outside the infrastructure Uptime Kuma is monitoring. If your homelab loses power, the VPS that runs this cron job is unaffected, and you get the alert.

Self-hosting Healthchecks.io: You can deploy your own instance via Docker Compose. See the Healthchecks.io Docker deployment guide for the Compose file. This keeps everything self-hosted while the watcher sits on a separate VPS or a friend’s homelab.


Updating & Maintenance

How to Update Uptime Kuma

Uptime Kuma releases frequently. Updating is a two-command process:

cd ~/docker/uptime-kuma
docker compose pull       # Pull the latest 1.x image
docker compose up -d      # Recreate the container with the new image

Uptime Kuma runs database migrations automatically on startup. The process takes under 10 seconds and your monitor history is preserved.

Backup Strategy

The entire state of Uptime Kuma — monitors, notifications, status pages, settings — lives in ./data/kuma.db (the SQLite database). Back this up.

Simple backup with tar:

# Run this before updates or on a cron schedule
tar -czf uptime-kuma-backup-$(date +%Y%m%d).tar.gz ~/docker/uptime-kuma/data/

Restore:

cd ~/docker/uptime-kuma
docker compose down
tar -xzf uptime-kuma-backup-20260607.tar.gz -C /
docker compose up -d

Version Pinning Policy

Strategy Example When to Use
louislam/uptime-kuma:1 Auto-updates within v1.x Production homelab — stable, gets patches
louislam/uptime-kuma:latest Always the newest release Testing/lab only — may include breaking changes
louislam/uptime-kuma:1.23.13 Exact version pin Mission-critical deployments — full control

The :1 tag used in this guide is the sweet spot: you get security patches and bug fixes automatically, but you will never wake up to a v2 migration without opting in.


Troubleshooting Common Issues

Monitors Show “Down” but the Service is Actually Reachable

Likely cause: Network isolation. Uptime Kuma runs in a Docker container with its own network namespace. If your monitored services are on a different Docker network, VLAN, or host interface, Uptime Kuma cannot reach them.

Fix: Ensure Uptime Kuma is on the same Docker network as the monitored services, or use the host’s IP address (192.168.1.50) instead of localhost or container names.

# Add Uptime Kuma to your existing proxy/traefik network
networks:
  - proxy_network

networks:
  proxy_network:
    external: true

Notifications Not Firing

  1. Click “Test” on the notification configuration — if the test fails, the credentials are wrong
  2. Check the monitor’s notification assignment — a monitor must have at least one notification channel assigned in its settings
  3. Check rate limits — Telegram limits bots to ~30 messages/second; Discord has per-webhook rate limits. If you have 50 monitors all going down simultaneously, some notifications may be throttled
  4. Verify the notification condition — by default, Uptime Kuma notifies on every status change. If you have “Resend Notification” set to a high number, you may be waiting for the resend interval

Status Page Not Loading Publicly

  1. Reverse proxy misconfiguration — the status page URL in Uptime Kuma must match the external URL. In Settings → Status Page, the “Domain” field should be https://status.yourdomain.com
  2. WebSocket blocked — status pages use WebSockets for live updates. If your reverse proxy strips WebSocket headers, the page loads but never updates. Enable WebSocket support in NPM or Traefik
  3. Cloudflare proxy cache — if you proxy through Cloudflare (orange cloud), ensure the status page subdomain has caching disabled (set to “Bypass” in Page Rules)

High CPU Usage

Uptime Kuma normally consumes under 1% CPU. If you see sustained CPU spikes:

  1. Too many monitors on too short an interval — 200 HTTP monitors at 20-second intervals is 600 requests/minute. Increase the interval to 60 or 120 seconds
  2. Certificate expiry checks on all monitors — this is a host-level integration, not per-monitor. Enable it once in Settings → Monitoring → “Certificate Expiry Notification”
  3. Browser dashboard open 24/7 — the dashboard uses WebSockets and real-time chart rendering. Close the browser tab when not actively monitoring

FAQ

Q: Can Uptime Kuma monitor services on another VLAN?

Yes, as long as the Docker host can route to that VLAN. If your Docker host sits on the management VLAN (192.168.1.0/24) and your IoT VLAN is 192.168.100.0/24, Uptime Kuma can monitor devices on the IoT VLAN — provided inter-VLAN routing is allowed. See our homelab networking guide for VLAN setup.

Q: How many monitors can I run on a Raspberry Pi 4?

Approximately 200 monitors at 60-second intervals before you notice CPU impact. Uptime Kuma is remarkably lightweight — each HTTP check is a single fetch() call.

Q: Does Uptime Kuma support SNMP for switch monitoring?

Not natively as of version 1.x. For SNMP monitoring of managed switches, pair Uptime Kuma with Prometheus + SNMP Exporter. Use Uptime Kuma’s Ping monitor for basic switch reachability.

Q: Can I run Uptime Kuma behind Authelia or Authentik SSO?

Yes. Place the SSO middleware in your reverse proxy layer, not in Uptime Kuma itself. In NPM, configure a custom location that requires Authelia authentication before proxying to port 3001. In Traefik, add the traefik.http.routers.uptimekuma.middlewares=authelia@file label.

Q: What is the difference between Uptime Kuma and Prometheus?

Uptime Kuma tells you if a service is up. Prometheus tells you how the service is performing. They answer different questions. Uptime Kuma is binary (up/down) and lightweight. Prometheus collects numeric metrics (CPU usage, request latency, disk I/O) over time and requires more resources. The two work together — Uptime Kuma for immediate outage detection, Prometheus for capacity planning and performance optimization.

Q: How do I monitor my VPS from my homelab?

Add a TCP monitor for SSH (port 22) and an HTTP(s) monitor for any web services running on the VPS. If the VPS has a public domain, monitor https://status.yourdomain.com from your homelab’s Uptime Kuma. For the reverse — monitoring your homelab from your VPS — run a second Uptime Kuma instance on the VPS or use the Healthchecks.io pattern described above.


Conclusion & Next Steps

You now have a production-ready Uptime Kuma deployment that monitors your entire homelab, alerts you via Telegram or Discord when something breaks, shows a public status page your family can check, and keeps itself honest with a Healthchecks.io dead man’s switch.

What to do next:

  1. Add more monitors — every service in your docker-compose.yml should have a corresponding monitor in Uptime Kuma
  2. Set up a dashboard TV — plug a cheap tablet or old monitor into a Raspberry Pi, open Uptime Kuma in full-screen kiosk mode, and mount it on the wall. Instant homelab nerve center
  3. Pair with metrics — deploy Grafana and Prometheus for deep performance dashboards; Uptime Kuma handles “is it up?”, Grafana handles “is it healthy?”
  4. Add a second Healthchecks.io check — monitor the health of your reverse proxy, your router, and your ISP connection. A five-minute cron job on a $5 VPS can tell you the difference between “Jellyfin crashed” and “your internet is down”
  5. Review your notification channels — during a real outage at 3 AM, which channel will actually wake you up? Configure at least two channels (Telegram + Email) for critical services

The homelab monitoring journey does not end here — it starts here. Every new service you deploy should come with the question: “How will I know when this breaks?” And now you have the answer.

What service will you monitor first?


Last updated: June 2026 — Uptime Kuma 1.x. Tested on Debian 12 with Docker 24+.