Uptime Kuma — Docker Compose Install
Deploy Uptime Kuma monitoring on Linux with Docker Compose. Persists data to a named volume and exposes the web UI on port 3001. Covers notification setup and monitor types.
yaml#!/usr/bin/env bash
# Uptime Kuma — self-hosted uptime monitor — Docker Compose install.
# Image: louislam/uptime-kuma:2 (major-version pin, gets minor updates)
# Docs: https://github.com/louislam/uptime-kuma/wiki
set -euo pipefail
INSTALL_DIR="/opt/uptime-kuma"
HOST_PORT=3001
mkdir -p "${INSTALL_DIR}"
cd "${INSTALL_DIR}"
cat > docker-compose.yml <<EOF
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
ports:
- "${HOST_PORT}:3001"
volumes:
- uptime-kuma:/app/data
restart: unless-stopped
volumes:
uptime-kuma:
EOF
docker compose up -d
echo ""
echo "Uptime Kuma is running at: http://$(hostname -I | awk '{print $1}'):${HOST_PORT}"
echo "Create your admin account on first visit."
What this does
Starts Uptime Kuma in a Docker container with a named volume so monitor history and settings persist across container restarts and updates. Uses the :2 major-version tag so docker compose pull delivers minor updates without a surprise major-version change.
Everything after this is configured through the web UI — no config files.
Why this approach
Uptime Kuma gives you a self-hosted status dashboard for everything in your lab — Plex, Home Assistant, Proxmox nodes, your router, external websites — with alerts to Telegram, Discord, email, or Ntfy when something goes down. The alternative is either knowing about outages because a family member tells you something isn’t working, or paying for an external monitoring service that polls your services from the internet. Uptime Kuma polls from inside your network, so it can reach LAN-only services that a cloud monitor can’t.
The named volume for data persistence is the single most important configuration decision in the compose file. Uptime Kuma stores its SQLite database — all your monitors, uptime history, and notification settings — in that volume. Without it, every container restart would start fresh. Using a named volume (rather than a bind mount) means Docker manages the data lifecycle, and the data survives docker compose down and docker compose up cycles automatically.
The :2 major-version pin (rather than :latest) is a deliberate choice for a monitoring service that’s supposed to always be running. :latest might pull a major version with breaking changes the next time you run docker compose pull. Pinning to :2 gets minor updates and patches within v2 automatically, while protecting against a v3 release changing the database schema or configuration format in a way that breaks your running instance.
Prerequisites
- Docker Engine + Compose plugin (docker-install-linux playbook)
- Port 3001 free on the host
First-time setup
- Open
http://SERVER-IP:3001 - Create an admin account (first account only — subsequent sign-up is disabled by default)
- Add monitors via Add New Monitor in the sidebar
Monitor types quick-reference
| Type | Use for | Key field |
|---|---|---|
| HTTP(s) | Web UIs, APIs | URL + expected status code (200) |
| TCP Port | Non-HTTP services (SSH, SMB) | host:port |
| Ping | Hosts with no open ports | hostname or IP |
| DNS | Domain resolution | domain + expected IP |
| Docker Container | Containers on the same host | mount the Docker socket (see below) |
| Push | Cron jobs that should check in | receives a GET to a unique push URL |
Monitor Docker containers directly (optional)
Mount the Docker socket so Uptime Kuma can query container health:
services:
uptime-kuma:
image: louislam/uptime-kuma:2
volumes:
- uptime-kuma:/app/data
- /var/run/docker.sock:/var/run/docker.sock:ro # add this
Then add monitors of type Docker Container, selecting the container name from the dropdown.
Set up notifications
Settings → Notifications → Setup Notification → choose a provider:
| Provider | What you need |
|---|---|
| Telegram | Bot token + chat ID |
| Discord | Webhook URL |
| Email (SMTP) | SMTP server, user, password |
| ntfy | ntfy server URL + topic |
| Gotify | Server URL + app token |
| Pushover | API token + user key |
After saving, test with the Test button, then enable the notification on individual monitors or set it as the default for all new monitors.
Create a status page
Dashboard → Status Pages → New Status Page. Choose a slug (URL path), select monitors to include, and publish. Share the URL http://SERVER-IP:3001/status/your-slug with family or teammates.
Upgrade Uptime Kuma
cd /opt/uptime-kuma
docker compose pull
docker compose up -d
The named volume retains all monitor history and settings.
Fedora / openSUSE
Same compose file works on any Linux with Docker. On openSUSE with firewalld:
sudo firewall-cmd --permanent --add-port=3001/tcp
sudo firewall-cmd --reload
macOS (Docker Desktop)
The compose file works with Docker Desktop on macOS. The Docker socket path is /var/run/docker.sock — same as Linux. Access via http://localhost:3001 or the machine’s LAN IP.
Windows (Docker Desktop with WSL2)
Works with Docker Desktop on Windows. Port 3001 is accessible at http://localhost:3001. The Docker socket path in WSL2 is /var/run/docker.sock when accessed from inside a WSL2 container.