Install is one container, one volume, port 3001, image louislam/uptime-kuma:2. The hard part is placement. A Kuma running on your homelab dies with your homelab, so it reports nothing during the only outage you care about. Put the primary instance on an external host and point it inward, or run a second small instance off-site purely to watch the first.
By LK Wood IV · 2026-08-15 · ~9 min read · St. Louis County, MO
Uptime Kuma installs in about ninety seconds. One container, one volume, one port. That part is genuinely easy, and every guide covers it.
Here is the part that decides whether the install was worth doing: a monitor that lives inside the network it watches cannot tell you that network went down. Put Kuma on your Proxmox box, point it at your NAS, your Jellyfin, your reverse proxy, and go to bed happy. Then the UPS gives up at 3am. Everything stops, including Kuma. Your phone stays quiet all night, because the thing whose job was to shout is on the floor with everything else.
You find out at 9am. The dashboard shows a clean green wall, because it has no memory of the hours it spent unpowered, and a gap in the record renders identically to a stretch of perfect health once the container comes back and resumes drawing bars.
I have watched people run this setup for months and conclude their homelab is extremely reliable. It wasn’t.
The install, briefly
Version 2.5.0 shipped on 1 August 2026. Pin the major tag.
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: unless-stopped
ports:
- "3001:3001"
volumes:
- ./data:/app/data
mkdir -p /opt/uptime-kuma/data && cd /opt/uptime-kuma
docker compose up -d
Open port 3001 and create the admin account on first load. That’s it. There is no separate database container. Kuma uses SQLite inside that one data volume, which is why this compose file is four lines of service definition instead of the five-container arrangement a Paperless-ngx stack needs. Version 2.x can talk to other backends for large deployments. For a homelab watching a few dozen endpoints, SQLite is correct and it is one fewer thing that can fail at 3am.
Do not publish 3001 to the internet. It is a login page standing in front of a complete map of your infrastructure, including hostnames and internal ports you would rather not advertise. Put it behind Nginx Proxy Manager or reach it over a WireGuard or Tailscale tunnel.
That is the whole tutorial. The rest of this page is about placement, which is where the value is.
Why placement is the whole problem
Uptime Kuma measures reachability. It sends a request and reports whether something answered. Every result it produces is therefore relative to one specific position on the network — its own.
From inside your LAN, Kuma can see that Jellyfin’s container is answering on port 8096. That is a real and useful fact. It is not the fact your users have. Your users are outside, and between them and Jellyfin sits your ISP, your modem, your router’s NAT and port forwarding, your DNS records, your certificate expiry, and your reverse proxy. Kuma checking http://192.168.1.40:8096 validates exactly one link in that chain and silently vouches for the rest.
So there are two distinct failure classes. One monitor position cannot cover both, and the table below is the reason I stopped treating a single green dashboard as evidence of anything.
| Failure | Seen from inside | Seen from outside |
|---|---|---|
| Container crashed | yes | yes |
| Disk full, service refusing writes | yes | yes |
| Certificate expired | no | yes |
| DNS record wrong or lapsed | no | yes |
| ISP down, modem dead, power cut | no — monitor is down too | yes |
| Port forward removed by a firmware update | no | yes |
| VPN tunnel to the monitor collapsed | n/a | shows as a false outage |
The bottom-left cell is the one that matters. When the whole site loses power, an internal monitor does not report an outage. It reports nothing at all, and nothing looks exactly like fine.
Two placements that work
Primary outside, pointed in. Run Kuma on a small external host and monitor your public endpoints the way a stranger would. This is the setup I would pick if I were only running one instance. It catches expired certificates, broken DNS, dead port forwards, and total site loss, because it is not standing on any of the things that break. Requirements are modest, which is the useful part: Kuma is a single Node process with a SQLite file, so the smallest tier at any VPS host is enough to watch a homelab’s worth of endpoints.
The trade is real. An outside instance sees only what you publish, so anything you never exposed to the internet is invisible to it, and that is usually most of the stack.
Two instances, watching each other. Keep the detailed instance inside, where it can reach every container and internal port. Add a second, nearly empty instance outside whose entire job is to watch the first one and a couple of public endpoints. Point each at the other’s health endpoint. Now an outage has to take out two separate sites and two separate uplinks before you hear silence.
This is the arrangement I would run for anything I actually cared about, and it costs one small VPS.
Do not try to solve this by having the outside instance reach in over a tunnel to check internal services. It sounds tidy. It fails badly, and in a specific way: the tunnel becomes a shared dependency, so every tunnel hiccup fires as a simultaneous outage across a dozen unrelated monitors, and after two weeks of that you will start ignoring the alerts. Which is worse than not having them.
The push monitor is the one people skip
Most Kuma monitors ask a question outward. The push monitor inverts that — it hands you a URL and waits to be called.
# at the end of your backup script
restic backup /data --repo "$REPO" && curl -fsS "$KUMA_PUSH_URL"
If the script finishes, Kuma hears from it. Good. If the script fails, hangs, or was never scheduled because the cron entry got clobbered, the call never arrives and Kuma alerts on the silence.
This catches a class of problem that no reachability check will ever see. Your backup host can be up, healthy, answering pings, and passing every HTTP check while quietly not having produced a backup in five weeks. I would put a push monitor on every scheduled job whose failure you would not notice for a month. Backups first.
Notification settings that avoid making you ignore it
The defaults are tuned to demonstrate the feature, not to survive contact with a homelab that reboots.
Set Heartbeat Interval to how fast you could genuinely respond. Sixty seconds is a reasonable floor. Set Retries to at least 3 before a monitor is marked down, so a container restart does not page you. Sixty seconds with 3 retries gives a service three minutes to come back on its own, which covers nearly every routine restart.
Add at least two notification channels through different infrastructure. Kuma supports over ninety providers. The reason for two is narrow but real: if you route everything through one service and that service is the thing that broke, your alert about the outage is part of the outage.
Then leave it alone for a week and count how many notifications you received that you did not act on. Every one of those is training you to dismiss the next one. Raise the retries until that count is near zero.
The status page, and whether you need a domain
Kuma’s status pages are genuinely good and cost nothing to set up. Group your monitors, mark which ones are public, and publish.
You need a hostname for it if the audience is anyone other than you. A status page at an IP address with a certificate warning does not reassure the household that the media server is coming back. If you are already buying a domain for your reverse proxy, a status. subdomain on it is free and takes about two minutes.
If the audience is only you, skip the domain and reach it over the tunnel.
What I have not tested
I have not run Kuma at a scale where SQLite is the constraint, so I cannot tell you where that boundary sits or whether moving to MariaDB is worth the extra container. Everything above is from homelab-scale use — dozens of monitors, not hundreds.
I have not measured Kuma’s resource use on the very smallest VPS tiers, and I would rather say that than quote a RAM figure I did not take. It is a single Node process with a SQLite file, so the tier below whatever you were considering is probably fine, but “probably” is doing real work in that sentence.
The 2.x non-SQLite backends I have not touched at all.
What getting this wrong costs
A silent monitor is worse than no monitor, because it converts an unknown into a false negative. You stop checking manually. You stop being suspicious. Then a drive fails in a mirror and the array runs degraded for three weeks, and the second drive fails, and the honest answer to “when did this start” is that nobody knows.
The install is ninety seconds. The placement decision is the part that determines whether any of it works, and it is the part almost every guide leaves out — including, for about a year, mine.
Frequently asked questions
Where should I run Uptime Kuma?
What port does Uptime Kuma use?
Which Docker image tag should I use?
Does Uptime Kuma need a separate database container?
Can Uptime Kuma monitor things that are not websites?
How do I stop alert spam during a reboot?
Evidence ledger
- Last updated
- Methodology
- This tutorial was written and edited by Lowell K. Wood IV in St. Louis County, MO. Specs and prices verified against vendor and project documentation current on the date above. Full editorial standard: methodology.
- Update log
- 2026-08-15 — Last reviewed and updated.
- Corrections
- Spotted an error or a stale number? Email hello@techfuelhq.com. Confirmed corrections are added to the update log above.