Skip to main content

How to Self-Host Uptime Kuma: Website Monitoring 2026

·OSSAlt Team
uptime-kumamonitoringuptimestatus-pageself-hostingdocker2026

TL;DR

Uptime Kuma (MIT, ~56K GitHub stars, Node.js) is a beautiful self-hosted uptime monitoring tool with a polished real-time dashboard. Monitor websites, APIs, TCP ports, DNS records, Docker containers, and databases. UptimeRobot's free plan limits you to 50 monitors with 5-minute intervals. Uptime Kuma is unlimited monitors at 20-second intervals, with a customizable public status page, for free.

Key Takeaways

  • Uptime Kuma: MIT, ~56K stars, Node.js — uptime monitoring with a gorgeous UI
  • Monitor types: HTTP/HTTPS, TCP port, Ping, DNS, Docker container, Push (for cron jobs)
  • Status pages: Public status pages — share uptime with customers or team
  • Alerts: 90+ notification services (Slack, Discord, Telegram, PagerDuty, ntfy, email)
  • Intervals: Down to 20 seconds (UptimeRobot free: 5 minutes)
  • Certificates: TLS certificate expiry monitoring with alerts

Part 1: Docker Setup

# docker-compose.yml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:latest
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - uptime_kuma_data:/app/data
      # For Docker container monitoring:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      TZ: America/Los_Angeles

volumes:
  uptime_kuma_data:
docker compose up -d

Visit http://your-server:3001 → create admin account.


Part 2: HTTPS with Caddy

status.yourdomain.com {
    reverse_proxy localhost:3001
}

Part 3: Monitor Types

HTTP/HTTPS (websites and APIs)

  1. + Add New Monitor
  2. Monitor Type: HTTP(S)
  3. URL: https://yourdomain.com
  4. Heartbeat interval: 60 seconds
  5. Retries: 3
  6. Save

Advanced options:

  • Expected HTTP status: 200 (alert if not 200)
  • Expected keyword: "Welcome" (alert if keyword missing — useful for detecting fake 200s)
  • Certificate expiry notification: Alert 30 days before cert expires
  • Authentication: Basic auth or bearer token

TCP port monitoring

Monitor SSH, databases, mail servers:

Monitor Type: TCP Port
Hostname: your-server.com
Port: 22      ← SSH
Port: 5432    ← PostgreSQL
Port: 3306    ← MySQL
Port: 25      ← SMTP

Docker container monitoring

Checks if a Docker container is running:

Monitor Type: Docker Container
Container Name: nginx
Docker Host: /var/run/docker.sock (local)

DNS monitoring

Check that DNS resolves correctly:

Monitor Type: DNS
Hostname: yourdomain.com
Record Type: A
Resolver: 1.1.1.1

Expected value: YOUR.SERVER.IP

Push monitoring (heartbeats for cron jobs)

For scheduled tasks — Uptime Kuma alerts if the job doesn't check in:

Monitor Type: Push
Generate a Push URL → copy the URL

# In your cron job, ping the URL on success:
0 2 * * * /opt/scripts/backup.sh && \
  curl -s "https://status.yourdomain.com/api/push/UNIQUE_TOKEN?status=up&msg=OK"

Part 4: Notifications

Slack

  1. Settings → Notification → Add notification
  2. Type: Slack
  3. Webhook URL: https://hooks.slack.com/services/...
  4. Channel: #alerts
  5. Test → save

Telegram

Type: Telegram
Bot Token: 1234567890:AAHdqTcvCH1vGWJxfSeofSs0K7MDk (from @BotFather)
Chat ID: -1001234567890 (your channel/group ID)

ntfy (self-hosted push)

Type: ntfy
Server URL: https://ntfy.yourdomain.com
Topic: uptime-alerts
Priority: High

PagerDuty (for production)

Type: PagerDuty
Integration Key: your-pagerduty-routing-key

Email (SMTP)

Type: Email (SMTP)
Host: mail.yourdomain.com
Port: 587
Security: TLS
Username: alerts@yourdomain.com
Password: your-email-password
From: alerts@yourdomain.com
To: you@yourdomain.com

Part 5: Status Pages

Create a public status page for customers or team:

  1. Status Pages → + New Status Page
  2. Slug: status (page at /status)
  3. Title: YourProduct Status
  4. Description: Real-time uptime and incident status

Add monitors to page

  1. Status Page → Edit → + Add group
  2. Group name: Core Services
  3. Add monitors: website, API, database

Custom domain

status.yourproduct.com {
    reverse_proxy localhost:3001
}

In Uptime Kuma → Status Pages → [page] → Custom Domain: status.yourproduct.com

Incident reporting

  1. Status Page → + Create incident
  2. Title: API degraded performance
  3. Content: We are investigating elevated error rates in the API.
  4. Status: Investigating → Identified → Monitoring → Resolved

Part 6: Monitor Groups and Tags

Organize many monitors:

Groups:
├── Production
│   ├── Website (https://yourdomain.com)
│   ├── API (https://api.yourdomain.com/health)
│   └── Database port (TCP 5432)
├── Development
│   ├── Staging (https://staging.yourdomain.com)
│   └── Dev API
└── Infrastructure
    ├── VPS SSH (TCP 22)
    └── Mail server (TCP 25)

Tags for filtering: production, critical, customer-facing


Part 7: REST API

# Authenticate and get API key:
# Settings → API Keys → + Add API Key

API_KEY="your-api-key"
BASE="https://status.yourdomain.com"

# Get all monitors:
curl "$BASE/api/v1/monitor" \
  -H "Authorization: Bearer $API_KEY" | jq '.[].name'

# Get monitor status:
curl "$BASE/api/v1/monitor/1" \
  -H "Authorization: Bearer $API_KEY" | jq '.heartBeatList'

# Add a monitor programmatically:
curl -X POST "$BASE/api/v1/monitor" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "http",
    "name": "New API",
    "url": "https://api.yourdomain.com/health",
    "interval": 60,
    "retryInterval": 60,
    "maxretries": 3
  }'

Maintenance

# Update:
docker compose pull
docker compose up -d

# Backup:
tar -czf uptime-kuma-backup-$(date +%Y%m%d).tar.gz \
  $(docker volume inspect uptime-kuma_uptime_kuma_data --format '{{.Mountpoint}}')

# Logs:
docker compose logs -f uptime-kuma

# Export monitor list (JSON):
# Settings → Export Configuration → Download

See also: Healthchecks — for monitoring cron jobs specifically

See all open source monitoring tools at OSSAlt.com/categories/devops.

Comments