Stashboard is a self-hosted homelab service dashboard that packs your entire home lab into a single Docker container — no separate database, no migrator sidecar, no manual secret management. Version 5.3, released this week, makes it the most complete self-hosted homelab service dashboard of its class by adding a full interactive SSH terminal to the Docker host, right inside your browser.
Why Build a Self-Hosted Homelab Service Dashboard?
Running a dozen containers means scattered bookmarks, uncertain service health, credentials sitting in a notes file, and a manual docker pull every time an update drops. The answer is a self-hosted homelab service dashboard that handles all of that in one place.
Stashboard’s design philosophy is blunt: a self-hosted homelab service dashboard that requires its own database container is a project, not a dashboard. Everything ships as one image. SQLite stores all data on a persistent volume. Migrations apply on startup automatically. If you’ve ever wrestled with a multi-container stack just to run a status page, this approach should feel like a relief.
Core Dashboard Features
Each service card shows a favicon (auto-resolved or custom), a live status dot, category badge, and tags. Click any card to open a four-tab modal:
- General — URL, display name, categories, tags, custom logo upload
- Healthcheck — HTTP check configuration, history, manual trigger
- Credentials — usernames, passwords, API keys, and notes encrypted at rest with AES-256-GCM. If you’re already self-hosting a password manager like Vaultwarden, Stashboard complements it for service-specific API keys and tokens that belong close to the service itself
- Docker — update tracking, container inspect, live logs, live stats, and one-click updates
Light / dark / system theme preference is saved server-side and synced across devices. Categories get custom colours. Tags are free-form. Deep links let you share a direct URL to any service modal.
Docker Update Tracking 🐳
This is where Stashboard earns its place as a practical self-hosted homelab service dashboard rather than a pretty bookmark manager. For each tracked container, it compares the running image digest against the registry and surfaces an Update badge — plus a single email notification — the moment a newer image is published. One notification per unique digest, no repeat spam.
Supported registries: Docker Hub, GHCR, Harbor, Nexus, Gitea Packages, AWS ECR, and any OCI Distribution v2-compatible registry.
Check schedules: Hourly (every 1 / 2 / 4 / 6 / 12 / 24 h), Daily at a fixed UTC time, or Weekly. Missed windows are caught on the next background tick — a server restart never permanently skips a check.
Tag filtering: Regex or semver-aware presets let you ignore -rc and -beta tags so pre-release pushes never trigger a false update badge.
GitHub Releases integration: For GHCR-hosted images, Stashboard fetches the matching GitHub Release and surfaces the changelog inline in the modal’s “What’s new” panel.
Webhook receiver: Per-watch, token-authenticated endpoint for instant registry push notifications, with the schedule-driven sweep as a fallback.
Dedicated instances page: The /docker page lists every container across every connected host with inline start / stop / restart, live CPU and memory sparklines, free-text search, and auto-refresh every 10 seconds. For live log tailing, each container’s log panel offers pause, resume, stop, clear, and snapshot download — a lighter alternative to running a dedicated tool like Dozzle alongside every host. If you’re familiar with Portainer, this covers the most common daily container operations without running a separate service.
New in v5.1 — Zero-Config Setup ⚡
Before 5.1, starting Stashboard required generating a base64 encryption key and a JWT secret by hand and writing them into a .env file. Miss either and the container refused to boot.
Version 5.1 removes that friction entirely. On first run, if neither secret is configured, the self-hosted homelab service dashboard generates cryptographically strong values — an AES-256 key and a 48-byte JWT secret — and persists them under .secrets/ on the stashboard-data volume. Every later restart reads them back, so image updates and container recreations never re-key your stored credentials. Back up the volume and you’re covered.
Supply your own keys via env vars and they take precedence; auto-generation is skipped for that secret. External secret managers and existing deployments are fully unaffected.
New in v5.2 — True Compose-Aware “Update Now” 🔄
The one-click Update now button (introduced in v2.7) has always used a Watchtower-style raw recreate: inspect the running container, pull the new image, stop, recreate with the preserved config, start. That works for standalone containers, but it bypasses Docker Compose — env_file resolution, depends_on ordering, and profiles are not honoured.
Version 5.2 fixes this for local-socket connections. Configure a Compose project path on the connection (bind-mount your Compose directory read-only into the Stashboard container), and clicking Update now on a Compose-managed container runs:
docker compose pull <service>
docker compose up -d <service>
Every env_file, every depends_on dependency, every profile — honoured exactly as docker compose up would. The raw recreate remains the fallback for remote hosts and containers without a Compose project path.
The button also now opens a proper confirmation dialog naming the exact image and container before anything runs, replacing the old browser window.confirm().
New in v5.3 — Browser SSH Terminal to the Docker Host 🖥️
The headline feature: the self-hosted homelab service dashboard now ships a full interactive SSH shell connected directly to the Docker host — not inside a container, but to the host machine itself — rendered in the browser with xterm.js.
A Terminal tab appears on every container modal. For LocalSocket and TCP+TLS connections it shows a disabled explainer. For SSH connections — where Stashboard has already been holding the private key since v2.5 — clicking Connect opens a live terminal session.
Security — Off by Default, Gated Three Ways 🔒
This is host-level remote code execution. It never activates implicitly. All three of the following must be true simultaneously:
- Server-wide toggle — Settings → Host terminal must be enabled. This is a DB-backed switch managed in the UI, with a full risk write-up on the Settings page — not an env var you can accidentally set.
- Per-connection opt-in — each SSH connection must have Allow host terminal explicitly checked.
- SSH connection type — LocalSocket and TCP+TLS connections are architecturally excluded.
Every session writes a row to the HostShellSessions audit table: who, when, which host, duration, bytes in, bytes out, and end reason. It also streams to the application log. Per-user and per-host concurrent session caps apply. A server-side idle timeout (default 10 minutes) closes dead sessions regardless of client state.
Because WebSockets can’t send a JWT Authorization header, authentication uses a short-lived single-use ticket: an authenticated POST to host-shell/ticket mints it, and the WebSocket opens with ?ticket=…. The ticket expires in 30 seconds and is consumed on first use — no ticket reuse, no long-lived session handles.
For a broader look at hardening your container setup, the Docker hardened images guide covers complementary security practices worth applying alongside Stashboard.
Quick Setup 🚀
curl -O https://raw.githubusercontent.com/VahaC/stashboard/main/docker-compose.yml
docker compose up -d
Open http://localhost:8080, register your first account, and click + Add service. No .env file required — the app generates its own secrets on first start and persists them to the volume.
To add a custom port, pin a specific version tag, or configure SMTP: copy .env.example to .env and edit only what you need. Everything has a built-in default.
What’s Coming Next 🗺️
The next phases on the roadmap:
- V5.4 — Compose project grouping on the instances page with a single Update project button per stack.
- V5.5 — Scheduled dangling-image cleanup, a storage widget, and a manual Prune now button.V5.5 — Scheduled dangling-image cleanup, a storage widget, and a manual Prune now button.
- V5.6 — Container exec: a browser terminal into a container using the same xterm.js + WebSocket transport from v5.3.
- V6.0 — Proxmox LXC update monitoring via the Proxmox REST API, with the same Hourly / Daily / Weekly schedule model and email notifications as Docker watches.
- V6.1 — Browser-based SSH client for Proxmox LXC (
pct enterwithout opening a local terminal).
Wrapping Up
Stashboard delivers everything a self-hosted homelab service dashboard should: live health checks, encrypted credential storage, Docker update tracking across every major registry, one-click container updates with Compose-aware recreation, live log and stats streaming, and — as of v5.3 — a browser SSH terminal to the Docker host itself.
As a self-hosted homelab service dashboard it installs in two commands, runs in one container, and doesn’t ask you to manage a database or generate cryptographic keys by hand.
Stashboard is open source — you can find the full source code on GitHub and pull the ready-to-run image directly from Docker Hub. Issues, PRs, and stars are always welcome. 🙌
