uptime-kuma Detailed Guide
Version 2.5.3~2.5.3 ο½ Category observability ο½ Security (reviewed) ο½ Sources: official project docs (English README/docs) + local measurements (2026-09-01)
Companion: site docs (manifest + guide + evidence) ο½ Quick version: site docs
1. Scenario: when to use it
You run a service (blog, API, home server, internal system) and everything is fine β until a user says "it's down" and you had no idea. You want something that probes your services every 30 seconds and tells you immediately when one is down, plus a public status page so users can check themselves. uptime-kuma does exactly that: self-hosted, free open source (MIT), Chinese UI, one Docker command.
Use it when:
- You run multiple machines/services and want one uptime panel;
- You want alert notifications (Telegram/Webhook/email etc.);
- You want a public status page (users check themselves instead of asking you);
- You want to notice services getting slower (heartbeats include ping latency).
Don't use it when: you need internal application telemetry (logs/traces/metrics) β that is logfire's job; you just need a one-off curl β no tool needed.
Division of labor with logfire: logfire = application telemetry (works with OpenAI SDK etc.); uptime-kuma = liveness probing. Complementary, not overlapping (matrix: possible-compatible).
2. Capability list
| Capability | What it does |
|---|---|
| Multiple probe types | HTTP(s) / TCP / Ping / DNS etc. (adjustable interval) |
| Heartbeat records | One record per probe (status: 1=up / 0=down + ping), the source of truth for monitoring |
| Alert notifications | Telegram / Webhook / email etc. (Webhook needs no account) |
| Public status page | /status/<slug> read-only page, pick monitors to publish |
| Data persistence | SQLite (kuma.db) in volume /app/data |
| Self-hosted | Data stays on your machine; MIT free open source |
3. Quick install
One command to start the container (measured China path: ghcr.nju.edu.cn prefix + volume):
# Source: Trove detailed guide Β· verified 2026-09-01
docker run -d --name uptime-kuma --restart=always -p 3001:3001 -v uptime-kuma:/app/data ghcr.nju.edu.cn/louislam/uptime-kuma:2.5.3
Expected output: a container ID; docker ps shows uptime-kuma Up (healthy after ~12 seconds, measured 2026-09-01)
Open http://localhost:3001: first visit runs setup (pick SQLite β create admin β login). Then "Add Monitor" on the left: type HTTP(s), URL target, interval 30s, save β first heartbeat within 30 seconds.
When monitoring host services (open-webui/ollama/your own API), use http://172.17.0.1:<port>, not 127.0.0.1 (measured pitfall: inside the container 127.0.0.1 is the container itself β all DOWN; 172.17.0.1 is the docker bridge gateway to the host).
Confirm:
docker psshows healthy;- http://localhost:3001 shows the setup page;
- after adding the first monitor, an UP heartbeat (green) appears within 30 seconds.
Install variants (deep dive)
| Path | Command | Status |
|---|---|---|
| Docker (recommended, measured) | ghcr.nju.edu.cn prefix + volume | β full-chain measured 2026-09-01 (2.48GB image) |
| Image pull fails | switch to another ghcr mirror (ghcr.dockerproxy.com etc.) or wait for a proxy window | not tested (ghcr.nju worked) |
| Bare metal / other platforms | official docs cover bare-metal and multi-platform | not tested (Docker form in this env) |
4. Why it works this way (mechanism & shared surfaces) (deep dive)
uptime-kuma is a Node.js app (GitHub louislam/uptime-kuma, MIT, 65k+ stars): a daemon sends probes (HTTP GET / TCP connect / Ping / DNS lookup etc.) to targets at the configured interval, writes each result (up/down, response time) to a database, renders the web UI, and triggers notifications.
Two key mechanisms:
- Heartbeat: each probe produces a record (status: 1=up / 0=down + ping), the single source of truth for monitoring; status pages and alerts are all derived from heartbeats.
- Container network isolation: the official recommendation is Docker (data in /app/data). 127.0.0.1 inside the container is the container itself β to monitor host services use 172.17.0.1 (docker bridge gateway, Linux/WSL) or host.docker.internal (Docker Desktop). Measured 2026-09-01: 127.0.0.1 targets all DOWN; switching to 172.17.0.1 β UP immediately.
Where it writes: Docker volume (data dir /app/data, SQLite kuma.db). Removing the container keeps data; removing the volume loses it.
5. Common operations
Step 1: setup + create admin
Explanation: first visit runs the setup wizard (database β admin β login).
# Source: Trove detailed guide Β· verified 2026-09-01
docker ps --filter name=uptime-kuma
Expected output: container Up (healthy, ~12s, measured 2026-09-01)
Browser http://localhost:3001 β SQLite β create admin β login to dashboard.
If stuck:
- container won't start β
docker logs uptime-kumatail; port 3001 busy β -p 3002:3001; - setup repeats β volume not mounted (data not persisted); confirm -v uptime-kuma:/app/data.
Step 2: add your first monitor
Explanation: a monitor is a probe target; HTTP is the most common type.
# Source: Trove detailed guide Β· verified 2026-09-01
docker exec uptime-kuma wget -qO- http://172.17.0.1:3000/api/health
Expected output: target service responds (verify reachability from inside the uptime-kuma container first; measured 2026-09-01: open-webui /health UP via 172.17.0.1)
UI: left "Monitors" β "Add Monitor" β type HTTP(s) β URL http://172.17.0.1:<port> β interval 30s β status codes 200-299 β save.
CLI equivalent (socket.io "add" event, measured):
# Source: Trove detailed guide Β· verified 2026-09-01
# socket "add"({name:"my-api", type:"http", url:"http://172.17.0.1:8080/health",
# interval:30, maxretries:1, accepted_statuscodes:["200-299"], conditions:[]})
Expected output: {"ok":true,"monitorID":1}; the monitor shows UP (green) after ~30 seconds
If stuck:
- always DOWN β verify the target is reachable from inside the container (wget or a temporary curl container); 127.0.0.1 is always DOWN (see "Why it works this way");
- save errors β v2.5's add event requires accepted_statuscodes/conditions etc. (missing conditions β NOT NULL error, measured); UI does not hit this;
- status stuck PENDING β wait one interval (30s) for the first heartbeat.
Step 3: verify heartbeats and DOWN detection
Explanation: heartbeats are the truth; verify both UP and DOWN before calling it done.
# Source: Trove detailed guide Β· verified 2026-09-01
# heartbeat query (socket.io "getMonitorBeats" event)
# socket "getMonitorBeats"(monitorID, 24) -> {"ok":true,"data":[{status:1,ping:16,time:"..."}]}
Expected output: latest record has status:1 with a ping value (measured UP=status:1, ping 16/104ms)
# Source: Trove detailed guide Β· verified 2026-09-01
# verify DOWN on purpose: stop the monitored service, monitor turns red in ~30s, restart to recover
docker stop open-webui && sleep 35 && docker start open-webui
Expected output: monitor goes DOWN (red) after stop, recovers UP after restart (measured 2026-09-01: down-probe judged DOWN correctly)
If stuck:
- no DOWN after stopping the service β check the interval; heartbeats are scheduled probes with latency;
- data survives restart β volume persistence OK (docker restart uptime-kuma keeps history, measured).
Step 4 (optional): notifications + public status page
Explanation: notification channels (Telegram/Webhook/email); Webhook needs no account and can be self-tested.
# Source: Trove detailed guide Β· verified 2026-09-01
# self-test a Webhook: curl your own webhook address first (example; configure your real one)
curl -s -X POST https://your-webhook.example/hook -H "Content-Type: application/json" -d '{"msg":"test"}'
Expected output: webhook service responds normally (200 or the service's defined success)
- Notifications: left "Notifications" β "Add Notification" β pick channel β fill address/credentials β attach to monitors. Not tested (zero-account red line; Webhook needs no account, configure per official docs).
- Status page: left "Status Page" β create β check monitors β get /status/<slug> public URL. Not tested (requires UI config).
If stuck:
- notification test fails β make sure it is configured under "Notifications", not inline on the monitor; self-test the Webhook with curl first;
- status page blank β at least one monitor must be checked and saved; public URL is /status/<slug>, not the root path.
6. Conflict pairs (summary)
Same source as the tool-page matrix; full pairs, states and evidence on the conflict matrix. Known relations:
- open-webui Γ uptime-kuma = compatible (verified): measured 2026-09-01 (uptime-kuma probes open-webui /health via 172.17.0.1 UP, ping 16ms) β prober and probed, naturally complementary;
- ollama Γ uptime-kuma = compatible (verified): measured 2026-09-01 (probes ollama /api/version UP, ping 104ms);
- logfire Γ uptime-kuma: complementary (app telemetry vs liveness probing), non-overlapping write surfaces, static: can coexist;
- Others: static possible-compatible (container volume write surface, no overlap).
7. Troubleshooting quick reference
- Symptom: all monitors DOWN β check whether URLs use 127.0.0.1 (container self-reference); switch to 172.17.0.1 (docker bridge gateway)
- Symptom: container not healthy after 12s β docker logs uptime-kuma tail; port conflict β change mapping
- Symptom: add event save error β v2.5 needs accepted_statuscodes/conditions fields (missing conditions β NOT NULL, measured); UI has no such issue
- Symptom: status stuck PENDING β wait one interval (30s) for the first heartbeat
- Symptom: data lost after restart β volume not mounted; confirm -v uptime-kuma:/app/data
Full four-section entries (symptomβcauseβfixβevidence): site docs (if recorded)
8. Uninstall & residue check
# Source: Trove detailed guide Β· verified 2026-09-01
docker stop uptime-kuma && docker rm uptime-kuma
docker volume rm uptime-kuma
Expected output: container stopped/removed; after volume removal docker volume ls no longer shows uptime-kuma
Note: removing the volume deletes all monitors/heartbeat history/status-page config. To keep data, remove only the container and keep the volume.
9. FAQ
- Q: Why are all host-service monitors DOWN? A: inside the container, 127.0.0.1 is the container itself. Monitor the host with http://172.17.0.1:<port> (docker bridge gateway, measured) or host.docker.internal (Docker Desktop).
- Q: Image won't pull? A: ghcr.nju.edu.cn measured working (2.48GB full pull); switch to another ghcr mirror or wait for a proxy window.
- Q: Where is the data, and does deleting the container lose it? A: SQLite at volume /app/data/kuma.db. With -v uptime-kuma:/app/data, deleting the container keeps data; deleting the volume loses it.
- Q: Does it overlap with logfire? A: No. logfire = internal app telemetry (logs/traces/metrics); uptime-kuma = service liveness + alerts + status page. Can coexist.
- Q: Do notifications need accounts? A: Telegram/email need credentials (not tested, zero-account); Webhook needs no account, configurable.
- Q: Where do I report issues? A: install/uninstall issues go through this entry's feedback; project issues go to the author repo.
- Version: 2.5.3 (manifest locked; image measured 2026-09-01).
- Environment: Docker 29.1.3 (WSL2 Ubuntu measured); RAM β₯1GB (lightweight, 12s healthy measured).
- Network: ghcr.nju.edu.cn measured working (2.48GB).
- Write surface: Docker volume uptime-kuma (/app/data, SQLite kuma.db).
- Port: 3001 (host mapping example; 3001 inside the container).
10. Sources
- Sources: official project docs (English README/docs) + local measurements (2026-09-01)
- Entry signature: louislam/uptime-kuma (MIT, kept as 2.5.3)
- Measured: `site docs (2026-09-01: ghcr.nju 2.48GB pull β container healthy in 12s β POST /setup-database sqlite β socket setup admin + login (token) β add 5 HTTP monitors β heartbeat verify: open-webui UP ping 16ms / ollama UP ping 104ms / bad target correctly DOWN; 127.0.0.1 self-reference pitfall reproduced end to end)
- Not tested: notification channels (Telegram/email need accounts, zero-account red line); public status page (requires UI config); bare-metal deployment.
Merged sources
This page merges multiple source articles β deduplicated by content hash, measured, and rewritten by AI. Sources are not scattered; they all live on this single page.
No merged sources yet: this page distills local verification and community rewrites; provenance details live on the linked solution page.