Uptime Kuma
Uptime Kuma checks whether your services answer — HTTP, TCP, DNS, keywords in a page, certificate expiry — and alerts you when one stops. Monitors, notification channels and status pages are all configured in its web interface. One container, with a SQLite database in its data directory.
Last run on a host 8 Nov 2026
Pinned at 2.5.9 (released 31 Oct 2026) · the newest upstream release
In the upstream images: 7 CRITICAL · 455 HIGH with a published fix — per image
To try it: Docker, nothing else. See Try it locally.
To deploy it behind the proxy: Traefik running and a domain.
Try it locally
Section titled “Try it locally”On your own machine, with no proxy, domain or certificate. From monitoring/uptime-kuma/:
cp .env.local.example .env.localdocker compose -f docker-compose.local.yml --env-file .env.local up -dThen open http://localhost:3001, choose SQLite on the database page and create
the owner account. Stop it again with the same command and down.
Installation
Section titled “Installation”From monitoring/uptime-kuma/:
-
Copy the environment file and set
APP_TRAEFIK_HOSTandTZ:Terminal window cp .env.example .env -
List
uptime-kuma-edgeinEDGE_NETWORKSincore/traefik/.env, then render and restart Traefik — see edge networks. -
Create the data directory and start the stack:
Terminal window mkdir -p volumes/datadocker compose up -ddocker compose logs uptime-kuma-app --followWait for
Listening on 3001. -
Open
https://<APP_TRAEFIK_HOST>straight away, choose SQLite and create the owner account. Whoever opens the page first becomes the owner, so do this before anyone else can reach it. -
Under Settings → About, switch off Show update if available. Uptime Kuma otherwise asks
uptime.kuma.petfor the newest version every 48 hours. The setting lives in the database, so it is a step after the first login.
Verify
Section titled “Verify”docker compose ps # one service, healthycurl -fsSI https://<APP_TRAEFIK_HOST>/ # 302 to /setup-database before setup, 200 afterThen add a monitor against a service you run and a notification channel, and use the channel’s Test button. Stop the monitored container: the monitor turns red and the alert arrives where you pointed it. Start the container again for the recovery alert.
Going further
Section titled “Going further”Who can reach it
Section titled “Who can reach it”The stack ships access-vpn, with limit-standard and headers-standard. The
interface shows every probe URL, the response bodies and the notification
webhook URLs, so it answers on your VPN and nowhere else.
A public status page
Section titled “A public status page”Status pages live at /status/<slug> and inherit the same access policy. To
publish one while the admin interface stays on the VPN, add a second router on
its own hostname with access-public in the first middleware position:
- "traefik.http.routers.kuma-public.rule=Host(`status.example.com`)"- "traefik.http.routers.kuma-public.service=uptime-kuma"# + the four middleware positions, access-public@file in the firstAlerts that reach you
Section titled “Alerts that reach you”Uptime Kuma sends to ntfy, Gotify, Matrix, webhooks, email and many more. A receiver on the same host stops when the host does, so the outage that most needs an alert would produce none — ntfy on a second host closes that gap. Uptime Kuma also only alerts while it runs itself; a dead-man’s switch covers that.
Browser and gRPC monitors
Section titled “Browser and gRPC monitors”Real Browser monitors run the Chromium inside the image, and gRPC monitors
use protobufjs. The findings in the evidence line above sit largely in those
two components. Point those monitor types only at targets you control. The
upstream -slim image ships without Chromium if you need no browser monitors.
Backup
Section titled “Backup”| State | volumes/data — SQLite at /app/data/kuma.db: every monitor, notification channel and credential |
| Critical | All of it. The configuration lives in the database, not in files |
| Quiescing | Dump rather than copy — the database is written continuously |
For borgmatic:
sqlite_databases: - name: uptime-kuma path: /srv/docker/monitoring/uptime-kuma/volumes/data/kuma.dbRestore order: stop the container, restore, start. Then send a test message through every notification channel — a restore is complete once alerts arrive again.
Updates
Section titled “Updates”-
Read the release notes.
-
Back up the data directory:
Terminal window cp -r volumes/data/ uptime-kuma-backup-$(date +%Y%m%d)/ -
Raise
APP_TAGin.env, then:Terminal window docker compose pull && docker compose up -d -
Check that the monitors are active and a notification channel still sends.
Troubleshooting
Section titled “Troubleshooting”Someone else is the owner. The first visitor to a new instance creates the
owner account. On a new instance with nothing to keep, stop the stack, remove
volumes/data, start it again and open the page yourself first.
The page answers 403. The request did not come over the VPN. That is the
access-vpn policy working; connect to the VPN or add a public status page as
above.
SQLite contention with many monitors. Above about 500 monitors the SQLite
database becomes the bottleneck. Uptime Kuma can use MariaDB instead
(UPTIME_KUMA_DB_TYPE=mariadb).
Files in volumes/data belong to root. The image runs as root and the stack
sets no user:, so files it creates there are root-owned. Read them with sudo.
Repository files
Section titled “Repository files”monitoring/uptime-kuma/README.md— setup, security model, what it sends outwardmonitoring/uptime-kuma/.env.examplemonitoring/uptime-kuma/UPSTREAM.md— source and upgrade checklist
Official sources
Section titled “Official sources”© 2026 SecDockBlueCode Apache-2.0Site content CC BY-NC 4.0