What you will set up
Uptime Kuma checks your websites and servers every minute, shows how long each has been up, warns before a certificate expires, and sends an alert when something goes down, to Matrix, email, Telegram, ntfy and many more.
Here it runs from its official rootless image, in Podman under a user of its own called kuma, behind Caddy from the Podman guide. Its alerts go to a room on the Matrix server from the Matrix guide.
Every step below was run on a Melonslab server with Debian 13:
- Uptime Kuma 2.5.5 checked a site elsewhere, an app on the same server and a ping to Quad9, and showed all three as up, with the site's certificate expiry.
- When a web app on the server was stopped, Kuma posted a Down alert in a Matrix room, and an Up alert when it came back.
- Kuma logged each login with the visitor's real address, and everything came back by itself after a reboot.
Uptime Kuma used about 130 MB of memory.
A monitor on the same server as the sites it watches cannot tell you that the server itself is down. For that, run Uptime Kuma on another server, and point it at this one.
Before you start
You need:
- a server set up as in the Podman guide, with Caddy running;
- an A record and an AAAA record for
status.example.compointing at your server; - for alerts in Matrix, a Matrix server as in the Matrix guide, and your own account on it.
The examples use status.example.com for Uptime Kuma, matrix.example.com for the Matrix server and @anna:example.com for your own Matrix account. Replace them throughout.
1. Create the user
As root:
useradd -m -s /bin/bash kuma
loginctl enable-linger kuma
machinectl shell kuma@
Everything up to step 4 runs as kuma.
2. Let Kuma reach this server
A rootless container normally shares the server's own addresses, so a check of an app on this server, such as https://matrix.example.com, would reach the container itself instead of Caddy. Give this user's containers addresses of their own instead. Create ~/.config/containers/containers.conf:
[network]
# Give containers their own address, so that the server's public address, and the apps behind Caddy, can be reached from them.
pasta_options = ["-a", "10.0.2.0", "-n", "24", "-g", "10.0.2.2", "--dns-forward", "10.0.2.3", "-a", "fd00::2", "-g", "fd00::1"]
The first part gives the container an IPv4 address, 10.0.2.0, and the second a private IPv6 address, fd00::2. Checks to the internet, over IPv4 and IPv6, work as before.
3. Describe the container
mkdir -p ~/.config/containers/systemd
Create ~/.config/containers/systemd/uptime-kuma.container:
[Unit]
Description=Uptime Kuma
[Container]
ContainerName=uptime-kuma
Image=docker.io/louislam/uptime-kuma:2-rootless
Volume=uptime-kuma:/app/data
# Only Caddy, on this server, can reach Uptime Kuma: the port is not open to the internet.
PublishPort=127.0.0.1:8095:3001
# ping needs raw sockets
AddCapability=NET_RAW
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
The 2-rootless image runs Uptime Kuma as an ordinary user inside the container too, and the tag follows every release of Uptime Kuma 2. NET_RAW lets its ping checks send ICMP, only inside the container's own network.
Start it:
systemctl --user daemon-reload
systemctl --user start uptime-kuma
systemctl --user enable --now podman-auto-update.timer
4. Put Caddy in front
Go back to root with exit, switch to machinectl shell caddy@, and add this block at the end of ~/Caddyfile:
status.example.com {
reverse_proxy 127.0.0.1:8095
}
Restart Caddy with systemctl --user restart caddy.
5. Set it up
Open https://status.example.com. Uptime Kuma first asks which database to use: choose SQLite, a single file in its volume, which suits a few dozen monitors, and Next. Then create your account, with a Username, a Password and Repeat Password, and choose Create.
Next, let Kuma see visitors' real addresses behind Caddy: open the profile menu at the top right, then Settings, Reverse Proxy, set Trust Proxy to Yes, and Save. Under Security in the same settings, you can also turn on two-factor authentication for your account.
6. Add monitors
Choose Add New Monitor. The ones you will use most:
- HTTP(s), for a website or web app: a Friendly Name and the URL. Kuma also tracks the site's certificate, and warns 21, 14 and 7 days before it expires.
- Ping, for a server: its Hostname or address.
- TCP Port, for a service such as mail or SSH: a hostname and a port.
Choose Save. Kuma checks each monitor every 60 seconds, which Heartbeat Interval changes.
7. Get alerts in Matrix
Kuma posts its alerts with a Matrix account of its own. As root, switch to machinectl shell matrix@, and create it, answering no to the admin question:
podman exec -it matrix-synapse register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
Name it kumabot. Then, from any computer, log in as it to get its access token, with the password you just set in place of BOT_PASSWORD:
curl -s -X POST https://matrix.example.com/_matrix/client/v3/login \
-H 'Content-Type: application/json' \
-d '{"type": "m.login.password", "identifier": {"type": "m.id.user", "user": "kumabot"}, "password": "BOT_PASSWORD", "initial_device_display_name": "Uptime Kuma"}'
Copy the value of access_token, and use it in place of ACCESS_TOKEN to create a room for the alerts, with yourself invited:
curl -s -X POST https://matrix.example.com/_matrix/client/v3/createRoom \
-H 'Authorization: Bearer ACCESS_TOKEN' -H 'Content-Type: application/json' \
-d '{"name": "Alerts", "invite": ["@anna:example.com"], "preset": "private_chat"}'
The answer has the room's room_id, which starts with !. Accept the invitation in Element. Then, in Uptime Kuma, open Settings, Notifications, and choose Set Up Notification:
- Set Notification Type to Matrix, and give it a Friendly Name.
- Enter
https://matrix.example.comas Homeserver URL, theroom_idas Internal Room ID, and the token as Access Token. - Turn on Default enabled, so that new monitors use it, and Apply on all existing monitors.
- Choose Test. A test message arrives in the room. Then choose Save.
From now on, Kuma posts a message such as [Zabbix] [🔴 Down] Request failed with status code 502 when a monitor goes down, and another when it is up again. The account can only post in the rooms it is in, and the room is not encrypted, so keep the alerts free of secrets. For email or another service, choose it as the Notification Type instead.
8. Back up
As kuma:
mkdir -p ~/backup
systemctl --user stop uptime-kuma
podman volume export uptime-kuma --output ~/backup/uptime-kuma.tar
systemctl --user start uptime-kuma
That saves the monitors, their history, your account and the notification settings, with the Matrix token. Copy ~/backup to another machine, and keep it private.
Troubleshooting
A Ping monitor is down with spawn EPERM. The AddCapability=NET_RAW line from step 3 is missing.
A monitor for an app on this server is down, while the app works in your browser. The containers.conf from step 2 is missing, or was created after the container started: restart it with systemctl --user restart uptime-kuma.
No alerts arrive. The notification is not on for that monitor. Edit the monitor, and tick the notification under Notifications, or edit the notification, and turn on Apply on all existing monitors.