labdeck

A small homelab dashboard that lives in one browser tab. It watches your services, and when one of them looks dead, you can SSH into the box right there without switching windows.

One Rust binary, one SQLite file, no build step for the frontend, no accounts to manage. You set a master password on first start and that's the whole setup.

What it does

Watches things. Add a service and pick how to check it:

  • http: accepted status codes (200, 200-299, 200,204,301-302), an optional "page must contain" string, and a switch for self-signed certs
  • tcp: a host:port that has to accept a connection
  • ping: shells out to the system ping, so you need iputils-ping installed

A service only flips to down after N failed checks in a row (you choose N), so one dropped packet doesn't wake you up. Every service gets a 24h uptime figure, a latency sparkline and a 24h strip you can hover. For HTTPS targets it also reads the certificate and warns you a week before it expires.

Lets you SSH in. Save a host with a password or a private key, hit connect, and you get a real terminal (xterm.js over a websocket, bridged to a PTY on the other end). Multiple tabs, a startup command per host (tmux new -A -s main is a good one, if the connection breaks during a long command), and saved snippets you can fire into whatever terminal is active. You can link a service to a host, which puts an ssh button right on its row.

The first time you connect to a host, labdeck remembers its key fingerprint. If it ever changes, the connection is refused and an event is logged. If you reinstalled the box on purpose, "forget host key" in the host settings resets it.

Tells you when stuff breaks. Down, back up (with how long it was down) and certificate warnings go to a webhook: Discord, Slack, Telegram, ntfy, or plain JSON to anything else. There's a test button.

Keyboard first. Alt+1 to Alt+5 switch views, Ctrl+K (or Alt+K, which also works inside a terminal) opens a command palette that can connect to hosts, run snippets, trigger checks and switch themes, / focuses the filter. Four themes: slate, amber, green, paper.

Run it

cargo run --release

Then open http://127.0.0.1:8787 and choose a master password (10+ characters).

variable default what it is
LABDECK_ADDR 127.0.0.1:8787 where to listen
LABDECK_DATA ./data directory holding labdeck.db

The frontend is compiled into the binary, so that one file is all you deploy. The data directory has to be writable by whatever user runs it.

If you bind to anything other than loopback, put it behind HTTPS (reverse proxy, tunnel, whatever you like). labdeck will remind you at startup, and it sets the Secure cookie flag based on X-Forwarded-Proto.

How secrets are handled

Your master password is run through Argon2id (64 MiB, 3 passes) to produce a key. SSH passwords, private keys and passphrases are encrypted with ChaCha20-Poly1305 using that key before they touch the database. The key only exists in memory while at least one session is logged in; when the last session expires or logs out, it's dropped, and terminals can't connect until someone unlocks again.

There is no recovery. Forget the master password and the stored credentials are gone. Changing it re-encrypts everything in one transaction.

Other bits worth knowing: sessions last 12 hours in an HttpOnly, SameSite=Strict cookie, state-changing requests need an X-Requested-With header, failed logins back off exponentially up to five minutes, and each terminal websocket needs a single-use ticket that's good for 30 seconds. Responses ship with a strict CSP.

Backup

Settings has an export that dumps services, hosts, snippets and the webhook settings as JSON. It deliberately leaves out SSH passwords and keys. If you want those too, copy the database file. They're encrypted in there.

Check history is kept for 14 days and events for 180.

Layout

src/
  main.rs     startup, shared state
  api.rs      routes, auth middleware, export/import
  auth.rs     sessions, tickets, login throttling, cleanup task
  vault.rs    Argon2id + ChaCha20-Poly1305
  db.rs       SQLite schema and queries
  health.rs   scheduler, the three check types, up/down state machine
  alerts.rs   webhook senders
  term.rs     websocket <-> SSH bridge
  web.rs      embedded assets, security headers
web/          vanilla JS, CSS, vendored xterm.js

Scope

Single user, single instance, no clustering, no agents on your machines. It checks from wherever it runs, so put it somewhere that can reach what you want to watch.

S
Description
Small homelab terminal dashboard
Readme
332 KiB
0 Stars 1 Watchers 0 Forks
2026-10-28 11:05:41 +01:00
Languages
Rust 54%
JavaScript 35.2%
CSS 9.9%
HTML 0.5%
Dockerfile 0.4%