Self-hosted monitoring is the most cost-effective way to keep an eye on your infrastructure. Uptime Kuma is a lightweight, open-source monitoring tool that runs on a single VPS with under 100 MB of RAM, supports unlimited monitors, and provides alerts via Telegram, Discord, email, ntfy, Slack, and more. This guide covers production-grade deployment with Docker Compose, reverse proxy configuration with automatic TLS, multi-channel notification routing, and a monitoring strategy that avoids alert fatigue.
Why Self-Hosted Monitoring?
External monitoring-as-a-service platforms charge per check, per monitor, or per seat. For a single VPS running multiple services, those costs quickly exceed the VPS itself. Uptime Kuma runs on infrastructure you already own, stores all data locally in SQLite, and gives you full control over check intervals, notification channels, and the public status page. The resource footprint is negligible: 60–90 MB RAM and 150–250 MB disk for the application and its database.
Production Deployment with Docker Compose
The Docker setup is the recommended path for production because it includes a restart policy, isolated filesystem, and easy upgrade path. Use Docker Compose to manage the container alongside a reverse proxy:
# docker-compose.yml for /opt/uptime-kuma/
version: '3.8'
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
restart: always
ports:
- "127.0.0.1:3001:3001"
volumes:
- ./data:/app/data
environment:
- UPTIME_KUMA_PORT=3001
- UPTIME_KUMA_HOST=127.0.0.1
healthcheck:
test: ["CMD", "node", "extra/healthcheck.js"]
interval: 30s
timeout: 10s
retries: 3
Start the stack:
cd /opt/uptime-kuma
docker compose up -d
docker compose logs -f # verify it starts cleanly
Reverse Proxy with Nginx and Automatic TLS
Never expose the Uptime Kuma admin interface directly. Run it behind a reverse proxy with TLS termination. Here is an nginx configuration with Certbot for automatic Let’s Encrypt certificates:
# /etc/nginx/sites-available/status.example.com
server {
listen 80;
server_name status.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name status.example.com;
ssl_certificate /etc/letsencrypt/live/status.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/status.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Obtain the certificate:
sudo certbot --nginx -d status.example.com
sudo nginx -t && sudo systemctl reload nginx
Monitor Configuration Strategy
Uptime Kuma supports multiple monitor types. Here is the recommended monitor set for a typical single-VPS web application:
| Monitor Type | Target | Check Interval | Retries | Purpose |
|---|---|---|---|---|
| HTTP Keyword | https://example.com/ | 60s | 2 | Catches both downtime and broken responses |
| TCP Port | example.com:22 | 120s | 1 | SSH reachability for emergency access |
| TCP Port | example.com:443 | 60s | 2 | Separate from HTTP check for diagnosis |
| DNS | example.com | 300s | 2 | Verifies DNS resolution is correct |
| Push (Heartbeat) | Backup cron job | 86400s | 0 | Silence = missed nightly backup |
| Ping | VPS gateway IP | 60s | 1 | Network-level reachability |
Group monitors into services using the “Parent Monitor” feature. For example, if the HTTP keyword monitor fails, the TCP port 443 monitor is automatically considered part of the same incident, reducing notification noise.
Multi-Channel Notification Routing
Uptime Kuma supports sending notifications to multiple channels simultaneously. Configure a tiered notification strategy:
- Primary channel (Telegram or Discord): Immediate alerts for all incidents. Set the notification to resend at most every 5 minutes to prevent spam during prolonged outages.
- Secondary channel (email via SMTP): Summary notifications only. Configure a daily digest or use a separate notification profile that only fires on “down” events.
- Heartbeat channel (Pushover or ntfy): For cron job monitoring. Each cron job sends a heartbeat; if the heartbeat is missed, the channel fires an alert.
To configure Telegram notifications:
# 1. Create a bot via @BotFather on Telegram
# 2. Get your Chat ID (send a message to the bot, then visit:
# https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates
# 3. In Uptime Kuma Settings > Notifications > Telegram:
# Bot Token: <YOUR_BOT_TOKEN>
# Chat ID: <YOUR_CHAT_ID>
# 4. Set "Send Notification" to true
# 5. Under "Message Options", check "Send only when a notification is sent"
# to avoid empty messages
Monitoring Cron Jobs with Push Heartbeats
The push monitor type is one of Uptime Kuma’s most powerful features. Instead of probing a service, the service reports its own health. This is ideal for cron jobs, backups, and batch processes that run on a schedule. Set up a push monitor in the Uptime Kuma UI, then add the heartbeat URL to your cron script:
#!/bin/bash
# /usr/local/bin/nightly-backup.sh
set -euo pipefail
# Run the backup job
/usr/local/bin/vps-backup.sh
# Report success to Uptime Kuma
curl -fsS -m 10 --retry 5 \
"https://status.example.com/api/push/YOUR_PUSH_TOKEN?status=up&msg=OK&ping="
If the cron job fails (and the script exits before the curl call), or if the cron job never runs, Uptime Kuma will fire an alert after the configured grace period.
Reducing Alert Fatigue
Too many alerts lead to ignored alerts. Configure these settings to keep notifications actionable:
- Retry count: Set to 2 for most monitors. A single failed check triggers a retry before declaring an incident. This filters out transient network blips.
- Notification interval: Set to 5 minutes minimum. This prevents the same incident from filling your chat with repeated messages.
- Maintenance mode: Use the built-in maintenance window feature during deploys, updates, and maintenance. Schedule recurring maintenance windows if you have a regular deployment cadence.
- Incident grouping: Use the “Parent Monitor” feature to group related monitors. If the web server goes down, you see one notification instead of three.
The Public Status Page
Uptime Kuma includes a built-in status page that shows uptime percentages, incident history, and per-service status. Configure it under Settings > Status Page. Best practices:
- Separate the status page from the admin panel: Use a different subdomain (e.g.,
status.example.comfor the public page,admin-status.example.comfor the admin interface). - Run a second instance on a different provider: If your main VPS goes down, the monitoring instance goes down too. For production-critical services, run a second Uptime Kuma instance on a different provider (as small as a $3/month VPS) and point the status page at that instance.
- Keep incident descriptions clear: Write human-readable descriptions for each incident so visitors understand what happened and what was done.
When choosing a provider for your monitoring VPS, compare VPS providers on our comparison table to find a cheap instance in a different region from your main application. The monitoring VPS needs minimal resources — 512 MB RAM and 10 GB storage is sufficient.
Backup and Migration
All Uptime Kuma data (monitors, notification settings, incident history) lives in a SQLite database at /opt/uptime-kuma/data/kuma.db. Back up this directory with your regular backup pipeline. To migrate to a new VPS:
# On the old VPS
tar czf /tmp/uptime-kuma-backup.tar.gz -C /opt uptime-kuma/data
# On the new VPS
sudo tar xzf /tmp/uptime-kuma-backup.tar.gz -C /opt
docker compose up -d
The migration is instantaneous because the database is a single file. No reconfiguration or re-adding monitors is needed.
A self-hosted monitoring stack that costs 90 MB of RAM and a few minutes of setup time is the cheapest insurance your VPS infrastructure can buy. For more on selecting the right VPS for your monitoring and application needs, check out the best VPS performance specs.




Leave a Reply
You must be logged in to post a comment.