Uptime Kuma Guide: Build a Beautiful Status Page with Docker

Monitor website and server uptime in real-time. Deploy Uptime Kuma via Docker Compose and configure custom notification alerts for incident response.

Self-Hosting Uptime Kuma: A Complete VPS Deployment Guide

Uptime Kuma is a self-hosted monitoring tool that provides real-time monitoring of websites, APIs, DNS records, and system ports. Deploying it on a Virtual Private Server (VPS) via Docker Compose ensures isolated environments, persistent data storage, and easy maintenance.

Production-Ready Docker Compose Configuration

Create a dedicated directory for Uptime Kuma on your VPS and define the environment configuration.

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

Save the following configuration as docker-compose.yml:

version: '3.8'

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: always
    security_opt:
      - no-new-privileges:true
    ports:
      - "127.0.0.1:3001:3001"
    volumes:
      - uptime-kuma-data:/app/data
    environment:
      - TZ=UTC
      - UPTIME_KUMA_PORT=3001
    healthcheck:
      test: ["CMD", "extra/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

volumes:
  uptime-kuma-data:
    driver: local

Configuration Breakdown

  • Docker Image: Uses the official louislam/uptime-kuma:1 image to lock major version updates while receiving patch releases automatically.
  • Port Mapping: Binds to 127.0.0.1:3001. This restricts direct access to Uptime Kuma from the public internet, routing traffic instead through a reverse proxy.
  • Data Persistence: Uses a named volume uptime-kuma-data mounted to /app/data to persist settings, monitoring history, and database backups.
  • Security Options: no-new-privileges:true prevents the container's processes from gaining new privileges via setuid/setgid binaries.
  • Healthcheck: Leverages the built-in health check script to detect application crashes and trigger Docker daemon auto-restarts.

Reverse Proxy Configurations

To access Uptime Kuma over HTTPS (highly recommended for production), configure a reverse proxy such as Nginx or Caddy.

Option A: Nginx Configuration with SSL

Create a virtual host configuration file (e.g., /etc/nginx/sites-available/uptime.example.com):

server {
    listen 80;
    listen [::]:80;
    server_name uptime.example.com;

    # Redirect all HTTP traffic to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name uptime.example.com;

    # SSL Certificates (managed by Certbot / Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/uptime.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/uptime.example.com/privkey.pem;

    # SSL hardening protocols
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:3001;
        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;

        # WebSocket support (Required for Uptime Kuma real-time dashboard)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Option B: Caddy (Simplest Configuration)

If using Caddy as your web server, the reverse proxy configuration and Let's Encrypt SSL certificate provisioning are handled automatically in your Caddyfile:

uptime.example.com {
    reverse_proxy 127.0.0.1:3001
}

Initializing the Deployment

Once the configuration files are defined, execute the following commands on your VPS shell:

  1. Pull and Start the Container: bash docker compose up -d
  2. Verify Container Running Status: bash docker compose ps
  3. Inspect Logs: bash docker compose logs -f

Hardening and Post-Installation Best Practices

Firewall Rules (UFW)

Ensure port 3001 is protected from direct public access. Only port 80 (HTTP) and 443 (HTTPS) should be open for external clients.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Local Database Backups

Uptime Kuma stores its data in an SQLite database inside /app/data/kuma.db. Implement a simple backup script to run via cron daily:

#!/bin/bash
BACKUP_DIR="/var/backups/uptime-kuma"
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
mkdir -p "$BACKUP_DIR"

# Safe hot-backup of the SQLite database
docker exec uptime-kuma sqlite3 /app/data/kuma.db ".backup '/app/data/kuma_backup_${TIMESTAMP}.db'"

# Move the backup file out of the container to host storage
mv ~/uptime-kuma/data/kuma_backup_${TIMESTAMP}.db "$BACKUP_DIR/"

# Retain only the last 7 days of backups
find "$BACKUP_DIR" -type f -name "*.db" -mtime +7 -delete