You spin up a dozen self-hosted services — Nextcloud, Vaultwarden, Jellyfin, your reverse proxy — and then you go to bed. You wake up in the morning and, somewhere in the night, three of them fell over. Nobody told you. Your family was locked out of Nextcloud for six hours.
Sound familiar?
That’s exactly the problem Uptime Kuma solves. It’s a self-hosted monitoring tool that watches your services 24/7 and screams at you (via Telegram, Discord, email, Slack, or 90+ other channels) the moment something goes down. It’s beautiful, it’s free, and it takes about 10 minutes to deploy.
This guide walks you through everything: Docker setup, adding monitors, configuring notifications, building a public status page, and hardening it behind a reverse proxy.
What Is Uptime Kuma?
Uptime Kuma is a self-hosted monitoring tool built by Louis Lam. Think of it as a self-hosted alternative to Uptime Robot — but you own the data, the alerts, and the status pages.
Key features at a glance:
- Monitors HTTP(s), TCP, DNS, Ping, Docker containers, keyword checks, and more
- 90+ notification channels (Telegram, Discord, email, Gotify, Pushover, Slack, webhooks…)
- Beautiful real-time dashboard with response-time graphs
- Public and private status pages — share service health with your users
- SSL certificate expiry monitoring
- 2FA support
- Multi-user support
- Maintenance windows (silence alerts during planned downtime)
It’s a single-container app, actively maintained, and has a genuinely great UI for something that’s fully open source.
Prerequisites
You’ll need:
- A Linux server (or NAS/VPS) with Docker and Docker Compose installed
- A domain name (optional but strongly recommended for the web UI and status pages)
- A reverse proxy (Nginx Proxy Manager, Traefik, or Caddy) — covered later
If you don’t have Docker set up yet, check our Docker guide for self-hosters.
Step 1: Deploy Uptime Kuma with Docker Compose
Create a directory for Uptime Kuma:
| |
Create your docker-compose.yml:
| |
Mounting the Docker socket (
/var/run/docker.sock) is optional but unlocks the ability to monitor your local Docker containers directly by name. If you do this, be aware that it grants Uptime Kuma significant access to your Docker daemon.
Start it:
| |
Uptime Kuma is now running at http://your-server-ip:3001. Open it in your browser and create your admin account — the first user to register becomes the admin.
Step 2: First Login and Dashboard Overview
After creating your account, you land on the main dashboard. The left sidebar shows all your monitors; the main area shows real-time status and response time graphs.
Before adding monitors, let’s set up notifications first — that way your alerts are ready to fire the moment a monitor detects downtime.
Step 3: Configure Notifications
Click the bell icon (🔔) in the top-right corner → Setup Notification.
Uptime Kuma supports a staggering list of notification channels. Here are the most popular ones:
Telegram (Recommended for Homelabbers)
- Create a bot via @BotFather on Telegram — type
/newbotand follow the prompts. Copy the Bot Token. - Start a chat with your bot, then visit
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdatesto find your Chat ID. - In Uptime Kuma, select Telegram as the notification type and fill in:
- Bot Token:
1234567890:ABCdef... - Chat ID:
987654321
- Bot Token:
- Click Test — you should receive a test message.
Discord
- In your Discord server, go to Server Settings → Integrations → Webhooks → New Webhook.
- Name it, choose the channel, copy the Webhook URL.
- In Uptime Kuma, select Discord and paste the webhook URL.
Email (SMTP)
For Gmail, use an App Password:
| Field | Value |
|---|---|
| Hostname | smtp.gmail.com |
| Port | 587 |
| Security | TLS |
| Username | youraddress@gmail.com |
| Password | your app password |
| From Email | youraddress@gmail.com |
| To Email | where to send alerts |
Gotify (Self-Hosted Push Notifications)
If you run Gotify (a self-hosted notification server), just paste your Gotify server URL and app token. Clean, simple, no third-party dependency.
Step 4: Add Your First Monitor
Click the "+ Add New Monitor" button. You’ll see a form with monitor types:
| Type | Use Case |
|---|---|
| HTTP(s) | Check a website/web app is responding (200 OK) |
| TCP Port | Check a raw port is open (databases, game servers) |
| Ping | ICMP ping — check a host is reachable |
| DNS | Check a DNS record resolves correctly |
| Docker Container | Check a local container is running (requires Docker socket) |
| Keyword | HTTP check that also scans the page for a specific word |
| gRPC | Monitor a gRPC endpoint |
| Steam Game Server | Yes, really |
Example: Monitor Nextcloud
- Monitor Type: HTTP(s)
- Friendly Name: Nextcloud
- URL:
https://cloud.yourdomain.com - Heartbeat Interval: 60 seconds
- Retries: 3 (prevents false alerts on transient blips)
- Notification: select the notification you just created
- Click Save
Uptime Kuma immediately starts checking. Within a minute you’ll see the first data points appear on the graph.
Example: Monitor a Database (TCP)
Say you have a MariaDB container on port 3306:
- Monitor Type: TCP Port
- Friendly Name: MariaDB
- Hostname:
192.168.1.100 - Port:
3306 - Interval: 60s
Example: SSL Certificate Monitor
Uptime Kuma automatically monitors SSL certificate expiry on any HTTPS monitor. By default, it will alert you when your cert is less than 14 days from expiry — configurable per monitor under Advanced Settings → Certificate Expiry Notification.
This is incredibly useful if you’re running your own Let’s Encrypt setup and want an early warning before your cert auto-renewal fails silently.
Keyword Monitor Example
Want to ensure Vaultwarden is actually serving the correct content (not just returning 200)?
- Monitor Type: Keyword
- URL:
https://vault.yourdomain.com - Keyword:
Vaultwarden - This fails if the page loads but doesn’t contain your expected text — useful for detecting misconfigured reverseproxy responses.
Step 5: Set Up a Status Page
A Status Page lets you share service health publicly (or privately) — great for communicating with family members, customers, or your community.
Click Status Pages in the left sidebar → + New Status Page.
- Name: “My Home Services” (or whatever you like)
- Slug:
status(your page will be athttp://your-kuma-url/status/status) - Custom Domain: if you want it at
status.yourdomain.com(set up via DNS + reverse proxy) - Add Groups and drag monitors into them:
- 📁 Media → Jellyfin, Audiobookshelf
- 📁 Storage → Nextcloud, Immich
- 📁 Tools → Vaultwarden, Gitea
- Toggle Public if you want it accessible without login
The status page auto-refreshes and shows live uptime percentages, incident history, and response time graphs. Looks great to share with anyone who uses your services.
Step 6: Put Uptime Kuma Behind a Reverse Proxy
Running Kuma on a raw port is fine for internal use, but you’ll want a proper domain + HTTPS if you’re accessing it remotely or sharing the status page publicly.
Option A: Nginx Proxy Manager (NPM)
If you’re using NPM (the most common reverse proxy for homelabbers):
- In NPM: Hosts → Proxy Hosts → Add Proxy Host
- Domain:
kuma.yourdomain.com - Forward IP:
<your server IP>or the Docker container name if on the same network - Forward Port:
3001 - Enable WebSockets — this is critical. Uptime Kuma uses WebSockets for real-time updates, and without this toggle it will appear to load but show a blank dashboard.
- Enable SSL and request a Let’s Encrypt cert.
Option B: Traefik Labels
If you’re using Traefik, add these labels to your docker-compose.yml:
| |
Option C: Caddy
In your Caddyfile:
| |
Caddy handles TLS automatically. Make sure Caddy and Uptime Kuma are on the same Docker network.
Step 7: Enable 2FA and Tighten Security
Even behind a reverse proxy, secure your Uptime Kuma admin account:
- Go to Settings → Security → Two-Factor Authentication
- Scan the QR code with any TOTP app (Aegis, Google Authenticator, Bitwarden)
- Enter the current code to confirm, save your backup codes somewhere safe
Other security hardening steps:
- Change your password if you used a weak one during setup
- Don’t expose port 3001 directly to the internet — always go through your reverse proxy
- If you only need to monitor internal services, keep Kuma entirely internal (no public exposure at all)
- Consider restricting the status page to a private URL if your service list is sensitive
Step 8: Maintenance Windows
Doing planned maintenance on a service? You don’t want a storm of false-positive alerts.
Go to Maintenance → + Schedule Maintenance:
- Title: “Nextcloud upgrade”
- Strategy: One-time or recurring
- Start Time / End Time
- Affected Monitors: select the ones you’re taking down
During the maintenance window, Uptime Kuma pauses alerting for the selected monitors and shows a “Maintenance” badge on the status page instead of “Down”. Clean, professional.
Monitoring Docker Containers Directly
If you mounted the Docker socket (/var/run/docker.sock), you can add Docker Container monitors:
- Monitor Type: Docker Container
- Container Name: the exact name from
docker ps(e.g.,nextcloud-app) - Docker Host: Local
This checks whether the container is running — it doesn’t check if the app inside is healthy, so it’s best combined with an HTTP monitor on the actual service URL.
Uptime Kuma Tagging and Organization
Once you have 20+ monitors, the dashboard gets busy. Use Tags to organize:
- In monitor settings → Tags → create color-coded tags like
critical,media,internal,external - Filter the dashboard by tag to focus on specific groups
Backing Up Uptime Kuma
All Uptime Kuma data lives in a single SQLite database at /app/data/kuma.db inside the container (mapped to the uptime-kuma-data Docker volume).
To back it up, simply copy the volume directory:
| |
Or, if you use a backup tool like Borg or Restic, point it at the volume path. See our homelab backup guide for a comprehensive backup strategy.
Troubleshooting Common Issues
Dashboard loads but shows a spinner / never updates
→ WebSocket connection failed. Make sure your reverse proxy has WebSocket support enabled (Nginx Proxy Manager: toggle “WebSockets Support”; nginx: add proxy_http_version 1.1, Upgrade, and Connection headers).
“ECONNREFUSED” on a Docker monitor
→ You haven’t mounted the Docker socket. Add - /var/run/docker.sock:/var/run/docker.sock:ro to your volumes.
False-positive “Down” alerts on a healthy service → Increase Retries (try 3–5) and adjust the Retry Interval. Single transient network blips shouldn’t trigger an alert.
HTTPS monitor shows “Invalid Certificate”
→ Check if the cert has actually expired (echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates). If it’s valid, the issue may be an intermediate cert not being served — check your SSL config.
Port 3001 in use
→ Change the host port in docker-compose.yml: "3002:3001" maps host port 3002 to the container’s 3001.
Final Thoughts
Uptime Kuma is one of those tools that earns its place in every homelab. It’s lightweight (barely 50 MB RAM), zero-maintenance, and gives you an instant, clear view of what’s up and what’s struggling across your entire self-hosted stack.
Once you’ve deployed it, spend 20 minutes adding a monitor for every service you run. Then create a status page and share it with whoever relies on your services. Future you — and your family — will thank you.
Want to go further? Combine Uptime Kuma with Gotify for self-hosted push notifications, or wire its webhook output into a Discord bot for a full self-hosted alerting stack with zero third-party dependencies.
Found this guide helpful? Check out our other monitoring and homelab guides at SelfHostWise.