Uptime monitoring that's made for the wall.
UptimeZen continuously checks your servers and services and shows their status on a glanceable, dark dashboard built to be left running on a screen. One tiny container, no database to run, nothing to npm install.
- HTTP · TCP · Ping checks
- ~80 MB image
- amd64 + arm64
Everything a home lab needs — and nothing it doesn't
Designed to be the calmest screen in the house. Powerful where it counts, invisible where it shouldn't get in the way.
Three check types
HTTP/HTTPS with status-code, keyword and self-signed TLS handling, raw TCP port checks, and ICMP ping — all from one place.
Glanceable dashboard
Big status tiles, live heartbeat bars where bar height is response time, rolling uptime %, and automatic grouping you can read across a room.
Per-monitor detail
Click any card for a response-time graph over 24h / 7d / 30d, uptime per window, min/avg/max latency, and a full incident log.
Drag-and-drop arrange
Reorder cards and groups — and move cards between groups — directly on the dashboard. Your layout is saved automatically.
Built for wall displays
Fullscreen kiosk mode, an auto-hiding cursor, layouts that scale up on TVs and 4K, and live updates with no flicker.
Tiny & self-contained
A single ~80 MB container — no external services, no separate database container, nothing else to wire up.
One file to back up
Everything persists to a single SQLite file in a mounted volume. Copy it and you have a complete backup of monitors and history.
Runs anywhere
Multi-arch images for linux/amd64 and linux/arm64 — the same build runs on an x86 mini-PC or a Raspberry Pi.
Zero dependencies
Built entirely on Node.js built-ins (node:sqlite, node:http). Nothing to compile, no native builds, no supply chain to worry about.
Status-aware ambient
NewThe whole background is part of the display: it glows a calm accent while everything is healthy, washes amber the moment something degrades, and turns red when a monitor goes down. You can read the state of your lab from across the room — before you can read a single number. Respects prefers-reduced-motion.
Instrument-style numerals
NewResponse times, uptime percentages and the clock are set in Space Mono, a self-hosted monospace — readouts stay crisp and don't jitter as values tick over. It ships as a bundled font file, not an npm package, so the zero-dependency promise still holds.
Slack notifications
Get a Slack message the moment a monitor goes down — and another when it recovers, with the downtime duration. Alerts fire on state changes only, never on every check, so the channel stays quiet until it matters. Paste an incoming-webhook URL, hit Send test, and you're live — with a per-monitor toggle to mute noisy ones. Zero extra dependencies; it's a plain HTTPS POST.
Optional password protection
Open by default — perfect on a trusted LAN. Set a single environment variable, UPTIMEZEN_PASSWORD, to put a login in front of the dashboard and API: one shared password, a signed session cookie, and rate-limited sign-ins. Change it later right from the UI; no per-user accounts to manage.
Calm by default, detailed on demand
See the whole lab at a glance, then click into any service for the full story.
From docker run to wall display in minutes
Run one container
Start UptimeZen with docker run or compose, mounting a data folder. On first run it seeds a few example monitors so you see it working immediately.
Add your services
Open the gear icon and add HTTP, TCP or ping checks — intervals, timeouts, expected status, keyword match, retries and "degraded over X ms". No config files required.
Put it on a screen
Each monitor runs on its own timer and stores results as heartbeats. Hit fullscreen, point a Raspberry Pi or mini-PC at it, and leave it on the wall.
Under the hood
A single Node.js process serves the dashboard, a JSON API and the static UI. A per-monitor scheduler runs self-rescheduling timers; the checker handles HTTP, TCP and ping probes with retries and redirects; results are written to SQLite and pruned on a retention window.
src/ ├── server.js HTTP server · JSON API · static files ├── db.js node:sqlite schema + queries ├── checker.js HTTP / TCP / ping probes (retry + redirect) └── scheduler.js per-monitor timers + history pruning public/ ├── index.html dashboard + manage drawer ├── styles.css dark, wall-display theme └── app.js live polling + manage UI
Up and running in one command
Then open http://localhost:3000 (or http://<server-ip>:3000). Your data lives in the mounted ./data volume, so it survives restarts, rebuilds and upgrades.
docker run -d \
--name uptimezen \
--restart unless-stopped \
-p 3000:3000 \
-v "$(pwd)/data:/app/data" \
-e TZ=Europe/Stockholm \
wahlstedt/uptimezen:latestThen update any time
docker compose pull
docker compose up -dAvoid docker compose down -v — the -v would delete your data volume. Everything else leaves ./data untouched.
Sensible defaults, easy to tune
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | HTTP port inside the container |
TZ | UTC | Timezone for displayed times (e.g. Europe/Stockholm) |
DB_PATH | /app/data/uptimezen.db | SQLite database location |
RETENTION_DAYS | 30 | How long heartbeat history is kept |
UPTIMEZEN_PASSWORD | (unset) | Set to require a login. Unset = open (no auth). |
UPTIMEZEN_SESSION_DAYS | 30 | How long a login session stays valid |
Volumes
| Path | Role | Purpose |
|---|---|---|
/app/data | Required | Holds the SQLite database — monitors and history. |
/app/config | Optional · read-only | Drop a monitors.json here to bulk-import on first run. |
A built-in HEALTHCHECK hits /api/health, so docker ps and orchestrators report container health out of the box.
UptimeZen is open by default — ideal on a trusted LAN. Set UPTIMEZEN_PASSWORD to put a login in front of the dashboard and API: a single shared password with a signed, rate-limited session that you can change later from Configuration → Change password. Even with a password set, don't expose port 3000 directly to the internet without TLS — keep it behind a reverse proxy or a VPN.
Give your home lab a screen worth looking at.
One tiny container. Zero dependencies. Your whole stack at a glance.