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:
- Nextcloud — HTTP monitor on port 8443
- Jellyfin — HTTP monitor on port 8096
- Pi-hole — DNS monitor on port 53
- Portainer — HTTP monitor on port 9443
- Home Assistant — HTTP 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:
- 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)
- Enable 2FA (optional but recommended if your dashboard is accessible outside your LAN) — Uptime Kuma supports TOTP-based two-factor authentication
- 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 showto 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:
- Message
@BotFatheron Telegram and create a bot with/newbot - Copy the bot token (looks like
123456:ABC-DEF1234ghikl...) - Send a message to your bot, then visit
https://api.telegram.org/bot<TOKEN>/getUpdatesto find your chat ID - In Uptime Kuma: Settings → Notifications → Setup Notification → Telegram
- Paste the bot token and chat ID, click Test, and confirm you receive the test message
Setting up Discord:
- In your Discord server: Server Settings → Integrations → Webhooks → New Webhook
- Copy the webhook URL (looks like
https://discord.com/api/webhooks/...) - In Uptime Kuma: Settings → Notifications → Setup Notification → Discord
- 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.
- Settings → Status Page → New Status Page
- Give it a name and a slug (e.g.,
homelab) - Pick which monitors appear — select the services your family cares about (Jellyfin, Home Assistant) but not internal-only ones (database, Docker socket)
- Customize the footer with your domain, a logo, and a custom message (“Having trouble? Message me on Signal.”)
- 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:
- Log into NPM at
https://npm.yourdomain.com:81 - Hosts → Proxy Hosts → Add Proxy Host
- Fill in:
- Domain Names:
uptime.yourdomain.com - Forward Hostname / IP:
uptime-kuma(the container name, if on the same Docker network) or192.168.1.50 - Forward Port:
3001 - Websocket Support: ✅ Enable (Uptime Kuma uses WebSockets for real-time dashboard updates)
- SSL tab → select “Request a new SSL Certificate,” check “Force SSL” and “HTTP/2 Support”
- 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)
- Create a free Healthchecks.io account at healthchecks.io — the free tier includes 20 checks
- Create a new check → name it “Uptime Kuma Heartbeat,” set grace period to 5 minutes, set schedule to “/5 * * * ” (every 5 minutes)
- 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:
- Every 5 minutes, the cron job hits your Uptime Kuma status page API
- If the response is HTTP 200 (Uptime Kuma is alive), it pings Healthchecks.io
- If the response is anything else (Uptime Kuma is down or unreachable), Healthchecks.io receives no ping
- 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
- Click “Test” on the notification configuration — if the test fails, the credentials are wrong
- Check the monitor’s notification assignment — a monitor must have at least one notification channel assigned in its settings
- 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
- 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
- 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 - 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
- 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:
- 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
- Certificate expiry checks on all monitors — this is a host-level integration, not per-monitor. Enable it once in Settings → Monitoring → “Certificate Expiry Notification”
- 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:
- Add more monitors — every service in your
docker-compose.ymlshould have a corresponding monitor in Uptime Kuma - 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
- Pair with metrics — deploy Grafana and Prometheus for deep performance dashboards; Uptime Kuma handles “is it up?”, Grafana handles “is it healthy?”
- 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”
- 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+.