Uptime Kuma is what everyone reaches for first. It's beautiful, it's well-documented, and it appears in every "self-hosted starter kit" list on Reddit. But if you've spent any time actually running it, you know the friction: it's built for uptime checks, not for telling you why your server is struggling at 2am. Beszel is different. Same self-hosted, same Docker Compose simplicity — but it watches your hosts, not your URLs.
These tools solve different problems. Most homelab guides treat them as alternatives. They're not — but you probably only need one right now, and picking the wrong one means ignoring half your dashboards within a week.
What Each Tool Actually Monitors
Uptime Kuma is an uptime monitor. HTTP, TCP, DNS, MQTT, keyword matching — it pings your services on an interval and alerts you when they stop responding. Its strength is breadth: monitor anything with a URL or port, configure alert channels (Discord, Telegram, Slack, ntfy, email), and visualise response times over time. It has no concept of CPU load, memory pressure, or container resource usage.
Beszel is a host and container metrics platform. It runs a hub (the web UI) and lightweight agents on each machine you want to monitor. Those agents ship CPU, RAM, disk, network, and per-container stats back to the hub. There are no HTTP checks, no keyword monitors, no ping-based alerts. It knows your containers are eating RAM; it doesn't know if your web app returns a 200.
The overlap is essentially zero. You're not choosing between them on features — you're choosing based on what question you're actually trying to answer.
Setting Up Uptime Kuma with Docker Compose
Straightforward to spin up:
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
volumes:
- uptime-kuma-data:/app/data
ports:
- "3001:3001"
restart: unless-stopped
volumes:
uptime-kuma-data:Hit http://your-host:3001, create an account, and you're in. Adding monitors is self-explanatory — pick your type, set the interval (60 seconds is fine for most services), and wire up an alert channel.
The bit the docs under-explain: notification channels need to be configured under Settings → Notifications before you add your first monitor, or you'll end up with silent failures. ntfy is the fastest to wire up if you already have it running; Telegram takes about five minutes with the BotFather flow.
Status badges are a useful touch — each monitor generates a /api/badge/:id/status SVG you can embed in internal dashboards. The status page builder is polished enough for sharing with family if you're hosting services for others.
Setting Up Beszel with Docker Compose
Beszel is two pieces: the hub (web UI and database) and the agent (deployed on every machine you want to monitor). They communicate over SSH-keyed connections — no credentials in environment variables, no open ports beyond what you expose.
Hub (on your primary machine):
services:
beszel:
image: henrygd/beszel:latest
container_name: beszel
ports:
- "8090:8090"
volumes:
- ./beszel-data:/beszel/data
restart: unless-stoppedLog in, go to Settings → Keys, and copy the public key. You'll need it for each agent.
Agent (on each host you want to monitor):
services:
beszel-agent:
image: henrygd/beszel-agent:latest
container_name: beszel-agent
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
PORT: "45876"
KEY: "your-hub-public-key-here"
restart: unless-stoppednetwork_mode: host is required — the agent needs access to host network interfaces to report accurate metrics. The Docker socket mount is optional but gives you per-container stats, which is most of the value.
Back in the hub UI, add a new system with the agent's IP and port 45876. The docs don't make this obvious: the connection test sometimes shows "offline" for 30–60 seconds while the agent finishes starting. Wait it out before you conclude something's broken — this cost me 20 minutes on first install.
For multi-host homelabs, repeat the agent compose file on each machine. The hub aggregates everything into a single view. If you're monitoring across a VPN — Tailscale's free tier covers most homelab setups — the agent IPs are just your Tailscale IPs. No extra config needed.
Alerting: Where They Diverge
Uptime Kuma wins on alerting breadth. It supports 90+ notification channels with granular control: alert after N consecutive failures, include heartbeat graphs in the notification, set maintenance windows to suppress alerts during planned downtime. If you run public-facing services or anything with informal SLAs, Uptime Kuma's alerting model is the right fit.
Beszel's alerting is intentionally minimal. Set CPU, RAM, or disk thresholds per system, pick a notification channel (email, webhook, Telegram, Slack, ntfy, Discord, Pushover, Gotify), and it fires when the threshold is crossed and clears when it drops. No escalation logic, no maintenance windows. That's enough for most homelab needs — "tell me when disk hits 90%" doesn't need sophistication.
One sharp edge with Beszel: threshold alerts don't have a cooldown by default, so a CPU that bounces around 85% can spam you. Set your thresholds conservatively (95% for CPU, 90% for disk) to avoid notification fatigue.
Resource Footprint and UI
Both are lightweight. Uptime Kuma idles around 60–80 MB RAM for a modest install with 20–30 monitors. Beszel hub is similar; agents are genuinely tiny at 10–15 MB each. Neither will stress a Raspberry Pi 4 or a refurb mini-PC like a Beelink running as a homelab hub.
Beszel's UI is noticeably more polished for infrastructure views. Charts load fast, the multi-host overview is clean, and the per-container breakdown is genuinely useful for debugging runaway processes. Uptime Kuma's UI is functional, but the monitor list gets unwieldy past 40–50 entries and there's no grouping beyond status pages.
The Verdict
Use Uptime Kuma if your primary concern is service availability — are my services reachable, are SSL certs about to expire, is my DNS resolving correctly. It's the right tool for protocol-based uptime checks and for anyone hosting services that others depend on.
Use Beszel if you want to know what's happening inside your hosts and containers — CPU spikes, memory leaks, disk creep, network saturation. It's the better fit for multi-host homelabs where a single pane of glass across machines matters. If you're running a NAS, a mini-PC, and a VPS on Hetzner for off-site workloads, Beszel's hub-and-agent model handles the spread cleanly.
Run both if your setup warrants it. The combined overhead is negligible, and they don't overlap. Use Uptime Kuma for "is it up?" and Beszel for "why is it slow?" — they slot together without stepping on each other.
The mistake most people make is installing Uptime Kuma and calling their monitoring done. You'll know a service is down; you won't know it ran out of memory 10 minutes before it died. That's the gap Beszel fills, and it's worth the ten minutes to deploy an agent on each host.
If you're building out the rest of your homelab stack, the phone-as-always-on LLM server guide covers wiring cheap local inference into n8n and Home Assistant — a natural next layer once your infrastructure visibility is sorted.