Uptime Kuma is a self-hosted monitoring tool: it checks your websites and services and alerts you when something goes down. It's one container, one volume, and it makes a perfect first app.

Prerequisites

  • A server with Docker Engine and the Compose plugin installed (the Docker Compose guide covers this)
  • An SSH login as a non-root user with sudo — from the security guide

1. Create the project folder

Run on the server, over your SSH session:

sudo mkdir -p /opt/uptime-kuma
cd /opt/uptime-kuma

2. Write the Compose file

Still on the server, create docker-compose.yml:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    volumes:
      - uptime-kuma-data:/app/data
    # Bound to localhost only — reached through an SSH tunnel (step 4)
    ports:
      - "127.0.0.1:3001:3001"
    restart: unless-stopped

volumes:
  uptime-kuma-data:
Why localhost binding? A plain "3001:3001" mapping publishes the app on every network interface, visible to the whole internet — including bots that probe for exposed dashboards. Binding to 127.0.0.1 keeps it private to the server itself. Note that Docker manages its own firewall rules ahead of ufw, so don't rely on ufw alone to block published ports.

3. Start the container

sudo docker compose up -d
sudo docker compose ps    # expect "running"
sudo docker compose logs -f uptime-kuma   # Ctrl+C to exit; logs keep it running

4. First access via SSH tunnel

Run this on your own computer (not the server), then open http://localhost:3001:

# On your local machine — forwards local port 3001 to the server
ssh -L 3001:localhost:3001 your-user@your-server-ip

The setup wizard appears. Create your admin account — there are no default credentials.

5. Updates

cd /opt/uptime-kuma
sudo docker compose pull
sudo docker compose up -d   # recreates the container if the image changed

Your data lives in the named volume, so updates never touch it. Before major version jumps (for example v2 to a future v3), read the project's release notes — some upgrades run one-way data migrations.

6. Backups

# Stop the app so the database file is consistent, then back up the volume
sudo docker compose stop
sudo tar czf uptime-kuma-backup-$(date +%F).tar.gz -C /var/lib/docker/volumes/uptime-kuma_uptime-kuma-data/_data .
sudo docker compose start

Move the archive somewhere off the server. Include this folder in the automated routine from the backups guide.

Troubleshooting

  • Nothing at localhost:3001 after tunneling: check sudo docker compose ps on the server — is the container running? Read sudo docker compose logs uptime-kuma for the first error line.
  • Port already in use: something else holds 3001 locally or on the server. Change the left side of the port mapping (for example "127.0.0.1:3002:3001") and tunnel to 3002 instead.
  • Permission denied on the volume directory: don't fight Docker's internal user by chowning volume files — stop the stack and let the container recreate what it needs, or check the project's documentation for the expected PUID/PGID handling.

Official documentation: Uptime Kuma wiki · Image tags: Docker Tags