monitor · verified 2026-09-01 ✓ Verified

uptime-kuma

Verified2026-09-01: ghcr.nju.edu.cn image full-chain verified (SQLite init, monitor creation, heartbeat UP/DOWN correct); monitoring host services from inside the container requires the 172.17.0.1 gateway address.

Self-hosted uptime monitoring with HTTP/TCP/Ping heartbeats, status pages and alerts; Docker one-command setup.

Category: monitor Complete entry Security: Security reviewed Domain: other Verified 2026-09-01 v2.5.3~2.5.3 Conflicts: open-webui: Compatible (measured); ollama: Compatible (measured) Source: Trove (independent adaptation, unofficial)

Install: 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

What you will run into

You run a service (blog, API, home server, internal system) and it works — until a user says "it is down" and you had no idea. You want something that probes your endpoints every 30 seconds and tells you the moment one fails, plus a public status page your users can check. You find uptime-kuma, but pulling the image from ghcr.io may time out, and after install your monitors all show DOWN because 127.0.0.1 inside the container is the container itself, not your host (measured 2026-09-01). This guide is the measured path: image via the ghcr China mirror (ghcr.nju.edu.cn, 2.48GB pull verified) and monitor host services via the 172.17.0.1 gateway address. After install you get a monitoring console at http://localhost:3001: add monitors, watch heartbeats, configure notifications, publish a status page. Use it when:

  • you self-host services/sites and want to know "alive? how fast?", with alerts on failure;
  • you want a public service status page (built in);
  • you have multiple endpoints (HTTP, TCP ports, Ping) you want on one dashboard.

Do not use it when: you need logs/traces/performance metrics — that is logfire's job (uptime-kuma probes liveness only); or you want a zero-maintenance cloud option (UptimeRobot/StatusPage, data leaves your machine).

Path: Quick fix (one command) → Step by step (jumpable) → How to confirm it works → Daily usage → Uninstall. In a hurry? Jump to "Quick fix".

Why this happens

uptime-kuma is a Node.js app (louislam/uptime-kuma on GitHub, MIT license, 65k+ stars): a daemon sends probes (HTTP GET / TCP connect / Ping / DNS lookup, etc.) to your targets on a configurable interval, stores every result (up/down + response time) in a database, and renders the web UI, status pages and notifications. Two key mechanics:

  • Heartbeat: every probe produces one record (status: 1=up / 0=down + ping latency). This is the single source of truth; status pages and alerts are all derived from heartbeats.
  • Container networking: the official install form is Docker (data in /app/data). 127.0.0.1 inside the container points at the container itself — to monitor services on the host (open-webui, ollama, your own API) use 172.17.0.1 (docker bridge gateway, Linux/WSL) or host.docker.internal (Docker Desktop). Measured 2026-09-01: monitors with 127.0.0.1 all went DOWN; switching to 172.17.0.1 flipped them to UP immediately.

What it touches: a Docker volume (data dir /app/data, SQLite database kuma.db). Removing the container keeps data; removing the volume deletes it. Division of labor with logfire: logfire = application telemetry (logs/traces/metrics); uptime-kuma = liveness probing (is it up, how fast). Complementary, not overlapping.

Quick fix (skip the walkthrough)

note: measured China path = ghcr.nju.edu.cn image prefix + mounted volume; host port example 3001 (use 3002 etc. if taken)

`agent 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

>>

预期输出: a container ID; docker ps shows uptime-kuma Up (healthy after ~12s, measured 2026-09-01)

  • After install open http://localhost:3001: first visit runs initialization (pick SQLite → create admin account → log in).
  • Then "Add monitor": type HTTP(s), URL = your target, interval 30s, save — the first heartbeat appears within 30 seconds.
  • When monitoring host services (open-webui/ollama/your API), use http://172.17.0.1:<port>, not 127.0.0.1 (measured pitfall, see FAQ 4).

Step by step

Step 1: pull the image and start the container

The official image lives on ghcr.io (GitHub Container Registry). Direct ghcr.io pulls are unreliable in China; the ghcr.nju.edu.cn prefix is measured working (2026-09-01, image 2.48GB). `agent docker pull ghcr.nju.edu.cn/louislam/uptime-kuma:2.5.3 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

>>

预期输出: pull prints 15 layers "Pull complete"; run prints the container ID

How to confirm:

  • docker ps shows uptime-kuma Up ... (healthy);
  • curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3001/ returns 302 (redirect to login/setup — normal).

If stuck:

  • Pull timeout → check network (use the nju prefix when ghcr.io is unreachable); otherwise configure a Docker registry mirror.
  • Port 3001 taken → use -p 3002:3001 and visit the new port.

Step 2: initialize the database and create the admin

The first visit to http://localhost:3001 enters initialization (a separate setup-database service in v2.5). Default SQLite is enough; no external database needed.

  1. Open http://localhost:3001 → initialization page → database type SQLite → submit;
  2. The page switches to the main service → create the admin account (username + password; weak passwords are rejected, measured);
  3. Log in.

Equivalent CLI path (measured, for automation/retesting): `agent curl -s -X POST http://127.0.0.1:3001/setup-database -H "Content-Type: application/json" -d '{"dbConfig":{"type":"sqlite"}}'

wait ~10s (setup-database shuts down, main server starts), then via socket.io:

socket "setup"(username, password) -> {"ok":true}

socket "login"({username,password}) -> {"ok":true, token}

>>

预期输出: {"ok":true}; login returns a 188-char token (measured 2026-09-01)

Step 3: add your first monitor

After login, "Monitors" → "Add monitor": type HTTP(s), URL = target, interval 30s, status codes 200-299, save. When monitoring host services (open-webui 3000 / ollama 11434 / your API), use http://172.17.0.1:<port> (measured 2026-09-01: the 172.17.0.1 gateway reaches the host; 127.0.0.1 monitors all went DOWN). Equivalent CLI path (socket.io "add" event, measured): `agent socket "add"({name:"my-api", type:"http", url:"http://172.17.0.1:8080/health", interval:30, maxretries:1, accepted_statuscodes:["200-299"], conditions:[]})

>>

预期输出: {"ok":true,"monitorID":1}; the monitor turns UP (green) within ~30s

Step 4 (optional): notifications + public status page

  • Notifications: "Notifications" → "Add" → pick a channel (Telegram/Webhook/email) → fill the webhook URL/credentials → attach to a monitor. Not measured (zero-account policy; no external notification configured; Webhook needs no account and can be configured from official docs).
  • Status page: "Status pages" → create → select monitors to expose → get a /status/<slug> public URL. Not measured (UI configuration; the core monitoring chain is fully measured).

How to confirm it works

  1. The monitor card shows its first heartbeat as UP (green):

`agent

heartbeat query (socket.io "getMonitorBeats" event, measured)

socket "getMonitorBeats"(monitorID, 24) -> {"ok":true,"data":[{status:1,ping:16,time:"..."}]}

>>

预期输出: latest entry has status:1 with a ping value (measured UP=status:1, ping 16/104ms)

  1. Test DOWN detection on purpose: stop the monitored service; within 30s the monitor turns red (DOWN); restart it and it recovers (the down-probe monitor correctly reported DOWN, measured).
  2. Data survives restarts: docker restart uptime-kuma, log in, history is still there (data lives in the volume).

Other environments

  • Docker Desktop (Windows/macOS): reach the host from the container via host.docker.internal:<port> (same convention already measured for open-webui in this repo); same ghcr.nju.edu.cn image prefix.
  • Synology/soft-router/Raspberry Pi: any Docker host works with the same run command; ARM images use the same nju prefix (not measured here — pick the right architecture tag).
  • Binary form: GitHub Release ships dist.tar.gz (7.3MB source bundle) requiring Node.js 20+ (npm run start-style; not measured — Docker is the recommended form here).
  • k8s: an official Helm chart exists (not measured); core = one StatefulSet + PVC, data dir /app/data.

Daily usage

Start & entry

  • docker start uptime-kuma; entry http://localhost:3001.
  • Logs: docker logs uptime-kuma --tail 20 (startup prints "Version: 2.5.3").

Common operations

  • Add monitors: "Monitors" → "Add monitor" → pick a type (HTTP/TCP/Ping/DNS/keyword — 12 types) → target → save.
  • Inspect heartbeats: open a monitor → "Heartbeat history" shows every probe with up/down and latency (queryable via socket "getMonitorBeats"(id, 24), measured).
  • Batch management: monitor list supports groups (tags/status pages), pause/resume per monitor.
  • Change interval: edit the monitor → interval in seconds — smaller is more sensitive but more requests; 30s is measured working.
  • Backup data: docker run --rm -v uptime-kuma:/app/data -v $(pwd):/backup alpine tar czf /backup/uptime-kuma-data.tar.gz -C /app/data . (pack the volume).

Data & directories

  • Everything lives in volume uptime-kuma at /app/data (kuma.db SQLite + uploaded assets). Backup = pack this directory.

Uninstall and cleanup

`agent docker stop uptime-kuma docker rm uptime-kuma

data directory (monitor config + heartbeat history; gone for good)

docker volume rm uptime-kuma

>>

预期输出: no output for stop/rm; volume rm prints the volume name uptime-kuma

note: the uptime-kuma volume is the monitor config + heartbeat history itself — only delete it after confirming you no longer need it.

Dependency warnings

  • Versions: v2.5.3 (released 2026-08-22, latest); Docker >= 20.10.
  • Environment: image 2.48GB (measured); ~512MB-1GB RAM is enough (Node process); port 3001 (default, host port swappable).
  • Environment (measured pitfall): 127.0.0.1 inside the container = the container itself — monitor host services with 172.17.0.1 (Linux/WSL bridge gateway) or host.docker.internal (Docker Desktop); 127.0.0.1 goes all DOWN (measured 2026-09-01, #1/#2 all DOWN, gateway flipped to UP).
  • Conflicts: complementary to logfire (liveness vs telemetry), not conflicting; no shared write surface with the other tools on this site — compatible (open-webui/ollama pairs verified with real UP probes, rest inferred).
  • China network: image via ghcr.nju.edu.cn (measured); monitor targets just need to be reachable from your network.

FAQ

  1. Why uptime-kuma instead of logfire? → logfire handles application telemetry (logs/traces/performance); uptime-kuma handles "is the service alive" liveness and alerts. Liveness → uptime-kuma, performance → logfire; complementary.
  2. Monitor always DOWN but the service is reachable? → the URL is probably wrong: 127.0.0.1 inside the container is the container itself. Use http://172.17.0.1:<port> (Docker Desktop: host.docker.internal). Measured 2026-09-01: 127.0.0.1 all DOWN, gateway address flipped to UP immediately.
  3. Which targets can I monitor? → HTTP(s)/TCP/Ping/DNS/keyword — 12 types; as long as the uptime-kuma container can reach the target (LAN targets need the container on the same network/gateway).
  4. Does data leave the machine? → All monitor data stays in the local volume; only notification channels (Telegram/Webhook) send out alert events (nothing leaves without a configured notification).
  5. How do I configure notifications? → "Notifications" → Add → pick a channel and fill credentials. Telegram needs a bot token (not measured, zero-account policy); Webhook needs no account and can be configured from the official docs.
  6. Is a public status page safe? → Status pages are read-only up/down views without admin features; still keep a strong password on the admin console.
  7. Multiple users? → Multi-user with permissions is supported (admin creation/login measured); the first account is the admin.
  8. Does data survive container restarts? → Yes. Data is in the volume (/app/data); removing the container keeps it; removing the volume deletes it.

← Trove | evidence & precheck records kept locally; conclusions and sources published here