How to install Uptime Kuma for basic monitoring
Table of contents
- Key takeaways
- What Uptime Kuma is and what to expect
- Prerequisites
- Docker installation
- What changed since 2.4.0
- Initial basic configuration
- Creating the first monitors
- Configuring Telegram notifications
- Configuring Discord notifications
- Public status page
- Test alerts with a monitor that fails on purpose
- Common mistakes to avoid
- Frequently asked questions
- Is Uptime Kuma free?
- What happens if the server running Uptime Kuma goes down?
- Does it support multiple users with different permissions?
- How do I recover the admin password?
- Conclusion
- Sources
Tested with Uptime Kuma 2.5.5 · Docker Engine 29.5 · Docker Compose v2 · verified
Updated: 2026-09-16
Uptime Kuma installs with Docker Compose and the louislam/uptime-kuma:2.5.5 image (not latest, which still points to 1.x), with a persistent volume at /app/data and port 3001. Bring the container up with docker compose up -d, pick SQLite on the first screen, then create the admin account.
Uptime Kuma is probably the most used open-source self-hosted uptime monitor today. Born in 2021 as a personal project by Louis Lam, it now has more than 90,000 stars on GitHub[1] and more than 180 million pulls of its image on Docker Hub. This guide covers how to install it with Docker reasonably, configure basic monitors, wire up Telegram and Discord notifications, and the operational mistakes people make the first time.
The steps were re-run on 16 September 2026 with Uptime Kuma 2.5.5, released that same day, on Docker Engine 29.5 and Docker Compose v2. The outputs shown below come from that run.
Key takeaways
-
Uptime Kuma fills the gap between "set up Prometheus + Blackbox Exporter + Alertmanager" and "pay a monthly subscription to UptimeRobot."
-
A single container covers HTTP, TCP, ping, DNS, gRPC and database checks, plus over 90 notification channels.
-
Pin the image tag: use
2or2.5.5, becauselateststill pulls the 1.x line. -
Configure backup from day one: all state lives in
/app/data; if that volume is lost, all configuration is gone. -
Don’t leave the interface exposed without HTTPS or strong authentication: Kuma stores sensitive notification credentials.
-
Validate alerts with an artificial monitor that fails on purpose before trusting the real flow works.
What Uptime Kuma is and what to expect
Uptime Kuma is a web application written in Node.js that monitors service availability through periodic checks and notifies when it detects failures. It supports a wide variety of check types:
-
HTTP/HTTPS with response-code and body-content validation.
-
ICMP ping, open TCP ports, DNS queries.
-
PostgreSQL, MySQL/MariaDB, SQL Server, Oracle, MongoDB and Redis, plus gRPC endpoints.
-
TLS certificate and domain expiry, as options on HTTP monitors.
-
Over a dozen additional types, including NTP (since 2.5.0) and SFTP (since 2.5.4).
The pragmatic pitch: fill the gap between "set up Prometheus plus Blackbox Exporter plus Alertmanager with hand-written rules" and paying an external service such as UptimeRobot. For teams with between five and a hundred services to monitor, it’s the most reasonable choice. Installation is one Compose file, one command and two browser screens, and configuration is visual, without YAML or code. It pairs naturally with a backup tool such as restic: restic protects the data, Kuma checks that the services are alive.
Prerequisites
-
A server with Docker installed. Any recent Linux distribution works; Debian 13 or Ubuntu 24.04 for stability. The image is published for amd64, arm64 and arm.
-
Resources: in our test, 100 HTTP monitors every 60 s against a local service kept the container between 114 and 162 MiB of RAM. CPU stayed under 1 % of one core apart from peaks of 6.4 %, on a shared machine with a load average of 40 across 18 cores. A VPS with 1 vCPU and 1 GB has headroom for that, although we did not test one.
-
Storage: the full image is about 600 MB compressed (1.8 GB on disk on arm64) and
2.5.5-slim, without the embedded MariaDB and Chromium, about 180 MB. The data directory grew from 1.4 MB to 4.4 MB in six minutes with 100 monitors. Every night, Kuma deletes heartbeats older than 24 hours that carry no status change, and keeps the daily summary for 365 days by default (Settings → Monitor History). -
Mount
/app/dataon a local disk or a Docker volume. The project does not support NFS, because SQLite needs POSIX file locks to avoid corruption. -
If exposing Kuma to the internet, you need a domain, valid certificates and a reverse proxy (nginx, Caddy, Traefik or Nginx Proxy Manager) that forwards the WebSocket
UpgradeandConnectionheaders. Kuma does not work under a subpath such as/kuma: it needs its own domain or subdomain.
Docker installation
The recommended way is Docker Compose with a small configuration file, pinned to version 2.5.5:
services:
uptime-kuma:
image: louislam/uptime-kuma:2.5.5
container_name: uptime-kuma
restart: unless-stopped
volumes:
- ./data:/app/data
ports:
- "3001:3001"
environment:
- UPTIME_KUMA_PORT=3001
healthcheck:
test: ["CMD", "extra/healthcheck"]
interval: 60s
timeout: 30s
retries: 5
deploy:
resources:
limits:
memory: 512M
Save it as docker-compose.yml and bring it up with docker compose up -d (the image is also published on Docker Hub[2]). The image already defines the same health check with a 180 s start period, and Docker keeps that period when it merges the Compose settings. If the reverse proxy runs on the same machine, publish the port as "127.0.0.1:3001:3001" so it is not open to the network.
Check the startup with docker compose logs; a fresh 2.5.5 install printed this (excerpt):
Welcome to Uptime Kuma
Your Node.js version: 22.22.3
2026-09-16T20:55:40Z [SERVER] INFO: Uptime Kuma Version: 2.5.5
2026-09-16T20:55:41Z [SERVER] INFO: Data Dir: ./data/
2026-09-16T20:55:41Z [SETUP-DATABASE] INFO: Starting Setup Database
2026-09-16T20:55:41Z [SETUP-DATABASE] INFO: - http://localhost:3001
2026-09-16T20:55:41Z [SETUP-DATABASE] INFO: Waiting for user action...
Open the browser at http://your-server:3001. Since 2.0, the first screen asks which database to use: embedded MariaDB (full image only), external MariaDB/MySQL or SQLite. Pick SQLite, which the screen itself recommends for small-scale deployments. Kuma stores the choice in data/db-config.json, and moving from SQLite to MariaDB later is not officially supported.
The next screen is "Create your admin account." Pick a strong username and password: Kuma requires at least 6 characters mixing letters and numbers, and has no email recovery. If you lose the password, reset it from inside the container:
docker exec -it uptime-kuma npm run reset-password
The script asks for the new password twice and shows it on screen as you type (omitted here). It then closes the other open sessions and ends like this:
Found user: admin
New Password:
Confirm New Password:
Connecting to ws://localhost:3001 to disconnect all other socket clients
Logged in.
Password reset successfully.
The 2.x line has been stable since 2.0.0 shipped on 20 October 2025, the same day as 1.23.17, the last 1.x release. Watch out for latest: the wiki marks it as deprecated, and in our test it still pulled 1.23.17. Use louislam/uptime-kuma:2 or a pinned version such as 2.5.5, released 16 September 2026.
Uptime Kuma has no multi-user support: setup creates a single account, rejects a second one, and 2.5.5 has no screen for adding users. For a small team, share that account with 2FA, or put a proxy with its own authentication in front.
What changed since 2.4.0
This guide was first written with Uptime Kuma 2.4.0 (31 May 2026) and moved to 2.5.3 on 2 September. On 16 September 2026 we re-ran the install on linux/arm64 against 2.5.5, marked Latest on the GitHub releases page[3]. The container passed its own extra/healthcheck, and a data directory created with 2.5.3 started with no database patches and its monitors, notifications and user intact. What the 2.5 line adds:
- 2.5.0[4] (1 August 2026): an NTP monitor type, no more 24-day cap on intervals, additional headers for SMTP notifications, a
next-rootlesstag,stat_dailyup/down columns widened to unsigned INTEGER, and new SMS providers. - 2.5.1[5] (22 August 2026): new notification providers (SMS Gateway, ClickUp, TurboSMTP, BearSMS, Pinglet and others).
- 2.5.2[6] and 2.5.3[7] (22 August 2026): a fix for non-Docker installs broken in 2.5.1, and a corrected version number; 2.5.3 is otherwise 2.5.1.
- 2.5.4[8] (11 September 2026): bumps JSONata to 2.2.2, which fixes CVE-2026-77415[9] (arbitrary code execution through crafted expressions, rated critical); closes a denial-of-service weakness the notes list as GHSA-wf2j-5mc7-5c4w; adds the SFTP monitor type and the Signalgrid, Notify! and Amoot SMS providers.
- 2.5.5[10] (16 September 2026): fixes a memory leak in TCP monitors.
If you run 2.5.3, the 2.5.4 fixes alone justify the upgrade. Version 2.5.3 bundles JSONata 2.1.1, inside the affected range, and Kuma uses that library to evaluate the JSON queries in its monitors. Stop the container, copy data, change the tag and bring it back up, as the migration guide[11] describes:
docker compose down
sudo cp -a data data-2.5.3
sed -i 's/uptime-kuma:2.5.3/uptime-kuma:2.5.5/' docker-compose.yml
docker compose up -d
docker compose logs -f
Initial basic configuration
On first entry, three things are worth adjusting:
-
Time zone under Settings → General. There are two: "Display Timezone" follows the browser by default, and the server time zone starts as UTC inside the container unless you set the
TZvariable. Set the server one toEurope/Madridif you operate from here. -
Two-factor authentication in Settings → Security with any TOTP app (Google Authenticator, Authy or 1Password): an important defensive layer.
-
If Kuma sits behind a reverse proxy, go to Settings → Reverse Proxy → HTTP Headers and set "Trust Proxy" to Yes. Without it, the recorded client IPs are the proxy’s and not the real ones.
Creating the first monitors
For each monitor, think in three axes: what I check (endpoint), how often (interval), and what counts as failure (conditions).
For public websites, the standard check is HTTP with the default 60-second interval. Verify at least the response code and, with the HTTP(s) keyword type, that the body contains a specific string. The latter is key: a monitor that only checks for 200 doesn’t detect when your application returns a pretty error page with code 200.
Since 2.0, new monitors are created with 0 retries, so a single failed check fires the alert. If a few seconds of downtime should not wake anyone up, raise "Retries" to 1 or 2 and adjust the retry interval.
For internal TCP-exposed services use the TCP Port type. Certificates have no type of their own. Enable "Certificate Expiry Notification" on the HTTP monitor (it is off by default) and set the thresholds under Settings → Notifications, which warns at 7, 14 and 21 days by default. Domain expiry notification, by contrast, is on for new monitors.
Group monitors by criticality (critical, important, informational) and by system. Tags filter the dashboard but do not route alerts, which are assigned monitor by monitor. To send severe alerts to their own channel, create a Group monitor with that channel and put the critical monitors inside it: the group goes down as soon as one child does. In our test, the group sent [Criticos] [🔴 Down] Child monitors down: CANARIO - no tocar.
Configuring Telegram notifications
Telegram is one of the most comfortable notification channels:
-
Talk to @BotFather on Telegram, follow instructions, and note the token it gives (the process is described in Telegram’s official bot documentation[12]).
-
Open a conversation with the bot and send
/start. The "Auto Get" button in Kuma’s form reads the chat ID; to do it by hand, openhttps://api.telegram.org/botyour_bot_token/getUpdateswith your token pasted right afterbot. For a group, add the bot to the group and do the same trick. -
In Uptime Kuma: Settings → Notifications → Set Up Notification, and pick Telegram as "Notification Type". Paste the token and chat ID, and test with the "Test" button.
To avoid assigning the notification monitor by monitor, tick "Default enabled" in the same form, which adds it to new monitors, and "Apply on all existing monitors" for the ones you already have.
Configuring Discord notifications
Discord uses incoming webhooks:
-
In your Discord server: channel settings → Integrations → Webhooks → New webhook. Copy the webhook URL.
-
In Uptime Kuma: Settings → Notifications → Set Up Notification → Discord. Paste the URL and choose optional name and avatar. Test and assign to desired monitors.
One detail worth knowing: Discord limits message frequency per webhook. Its rate limits documentation[13] says limits are calculated per webhook, may change and should not be hard-coded; past the limit, the API answers with HTTP 429. If you have 100 monitors and they all fail at once, Discord may start rejecting messages and you’ll lose alerts.
As the monitor count grows, put the critical monitors under a Group monitor with a single alert, or use an intermediary such as ntfy or a dedicated on-call service.
Public status page
In the header: Status Pages → New Status Page. Enter a name and a slug, then choose in the editor which monitors to show, the theme and the domain names.
The recommended practice is at least two pages:
-
A public one with user-facing services.
-
An internal one with all monitors including internal ones. This lets you communicate status to clients without revealing infrastructure detail.
Kuma does not password-protect status pages: anyone who knows the /status/ path followed by the slug can see one. Protect the internal page with the reverse proxy’s authentication, or keep it reachable only over VPN.
Test alerts with a monitor that fails on purpose
Setting up Telegram or Discord and seeing the test message only proves that the token is valid. It does not prove you will hear about a real outage: the test button does not follow the same path as a monitor that changes state. The cheap way to check is to cause a real outage on something that does not matter.
-
Create an HTTP monitor against a closed port, for example
http://127.0.0.1:9, or against a made-up domain. Give it an obvious name such asCANARIO - no tocar. -
Lower its interval and retries (for example 20 s and 1 retry) so you do not wait. Attach it to every notification channel you want to validate, not just one.
-
Wait for the down alert. In our 2.5.5 test, the monitor went pending on the first failure and the alert went out 20 s later with the text
[CANARIO - no tocar] [🔴 Down] connect ECONNREFUSED 127.0.0.1:9. If it never arrives, the problem is the channel, not your service, and you found out calmly rather than at three in the morning. -
Point the monitor at something that responds and confirm the recovery alert arrives too (in the test,
[CANARIO - no tocar] [✅ Up] 200 - OK). It is the one people forget, and the one that tells you the incident is over. -
Leave the canary paused, not deleted. When you change token, channel or version, you resume it for a minute and get the same certainty back.
Repeat this check every time you touch the notification settings. An alert that never fires is indistinguishable from having no monitoring.
Common mistakes to avoid
-
Not configuring backup: Uptime Kuma stores everything in
/app/data; if that volume is lost, you lose all configuration and history. Since 2.0, copying that directory is the only supported backup method, because the JSON export was removed. -
Leaving the interface exposed without HTTPS or strong authentication: Kuma handles sensitive credentials. Exposing it with a weak-password admin hands over an entry point to your infrastructure.
-
Not validating notifications: after configuring Telegram or Discord, test with an artificial monitor that fails on purpose. Don’t trust it’s working because you saw the test message; the real "monitor fails, alert sent" flow has more pieces.
-
Too-aggressive intervals: a 10-second interval sends six times as many requests as a 60-second one, both to your services and to Kuma’s database. The 60-second default is a sound starting point.
Frequently asked questions
Is Uptime Kuma free?
Yes. It is open-source software under the MIT license, with no license cost and no monitor limit. The only real expense is the server you run it on.
What happens if the server running Uptime Kuma goes down?
You stop receiving alerts for as long as the outage lasts, because the monitor cannot watch itself. If monitoring is critical, an independent external heartbeat (another Kuma instance on a different provider, or a third-party status service) that tells you when Kuma itself stops responding is worth setting up.
Does it support multiple users with different permissions?
No. Uptime Kuma 2.5.5 has a single admin account: setup rejects a second one and there is no user-management screen. If other people need access, share the account with 2FA enabled, or put a reverse proxy with its own authentication and access control in front.
How do I recover the admin password?
Run docker exec -it uptime-kuma npm run reset-password and type the new password twice. The script closes the other open sessions, and in our test the new password worked straight away. There was no need to restart the container or edit the database by hand.
Conclusion
Uptime Kuma solves a bounded problem well. It doesn’t try to be Grafana, it doesn’t try to be Prometheus with complex rules, it doesn’t manage application metrics. It does one thing (check if your things are alive and alert you if not) with enough simplicity that a small team can maintain it without spending significant time.
For a team just entering serious monitoring, Uptime Kuma is probably the best first piece to install before anything else. It gives you immediate basic coverage and teaches you the discipline of thinking about what deserves monitoring. When the time comes to add deeper observability with Prometheus or a full stack (such as SRE dashboards with AI), Kuma will keep covering its layer without interfering. It does its job and disappears from the radar until something fails, which is exactly what you ask of an uptime monitor.
Read the Spanish version of this article: Cómo instalar Uptime Kuma para monitorización básica.