# 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 ```sh 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.