Sign inSign up

vahac/stashboard

By vahac

Updated about 13 hours ago

Self-hosted homelab dashboard — one place for every service you run.

Image
Networking
Developer tools
Monitoring & observability
0

3.5K

vahac/stashboard repository overview

Stashboard

Self-hosted homelab dashboard — and a full Docker / Proxmox control plane — in one container.

Stashboard started as a dashboard for the services you run at home and grew into the place you actually manage them from: every container on every Docker host, every Compose stack, every LXC and VM on your Proxmox nodes, with health, updates, logs, shells and notifications in one UI.

Ships as a single image (vahac/stashboard) with SQLite inside — no separate database container, no migrator sidecar. ASP.NET Core 10 API serving a React 19 SPA.


Quick start

curl -O https://raw.githubusercontent.com/VahaC/stashboard/main/docker-compose.yml
docker compose up -d

Open http://localhost:8080, register the first account, click + Add service.

No keys to configure. On first start the app generates its encryption key and JWT secret and persists them under /app/Data/.secrets on the stashboard-data volume, so an image update never re-keys your data. A .env file is optional — add one only to change the port, pin a tag, or supply your own secrets/SMTP.

Back up the stashboard-data volume. It holds the SQLite database and the encryption key. Lose the key and every stored credential is permanently undecryptable.

Minimal manual run:

docker run -d --name stashboard \
  -p 8080:8080 \
  -v stashboard-data:/app/Data \
  -v stashboard-uploads:/app/wwwroot/uploads \
  vahac/stashboard:latest

What it does

The dashboard

Each service is a card with its favicon (or an uploaded logo), live status dot, category badge and tags. Click it for a tabbed modal:

  • General — URL, display name, categories, tags, custom logo
  • Healthcheck — HTTP main/additional URLs plus an independent monitor (TCP port, ICMP ping, DNS, or HTTP keyword), history, manual "Check now"
  • Credentials — usernames, passwords, API keys and notes encrypted at rest (AES-256-GCM)
  • Docker — image-update tracking, inspect, live logs, live stats, one-click update

Plus: TLS certificate-expiry tracking with warn/critical thresholds, per-user categories and tags, light/dark/system theme synced across devices, deep links, and a command palette (Ctrl/+K) that fuzzy-searches services, containers, Compose projects, Proxmox guests and every page.

Docker management

A dedicated Docker page lists every container across every connected host — local socket, remote TCP+TLS, or SSH-tunnelled daemon — grouped by Compose project, with inline Start / Stop / Restart (and optional Remove), health state, and per-host summary and storage widgets.

  • Image-update tracking — compares the running container's digest against the registry (Docker Hub, GHCR, self-hosted Basic-auth registries such as Harbor / Nexus / Gitea, AWS ECR), with regex tag filtering, hourly / daily / weekly schedules, and a token-authenticated webhook receiver for instant pushes
  • One-click "Update now" — pulls and recreates the container in place; Compose-managed projects get a true compose pull + up -d <service> recreate that honours env_file, depends_on and profiles. Post-update health verification, and every attempt written to an immutable audit log. It can even update Stashboard itself, via a detached helper container
  • Diagnostics — full inspect panel (secrets masked), real-time log streaming with stdout/stderr toggles and snapshot download, and per-second CPU / memory / network / block-I/O stats with sparklines
  • Visual Compose editor — projects are auto-discovered from container labels; edit image (with a registry tag dropdown), ports (with collision checks), volumes, env, labels, command, restart policy and resource limits bounded by the host's real CPU/RAM. Shared networks / volumes / secrets / configs get their own tab. Saves are surgical (comments and key order survive byte-for-byte), validated with docker compose config -q. A dependency graph view and a linter (port collisions, depends_on cycles, missing healthchecks, escaping bind mounts, :latest tags) round it out
  • Create a project from a pasted docker-compose.yaml — paste or upload, dry-run parse + lint + config -q, then deploy
  • Adopt existing containers and stacks — bring containers Stashboard never created under management: orphaned Compose projects get their file written back (nothing restarts), and plain docker run containers are reconstructed as a reviewed Compose file with existing volumes/networks declared external: true, with atomic rollback
  • Stacks that are down stay visible — projects with no running containers appear in a Not deployed group with Deploy / Open / clean-up, plus an optional bounded disk scan of your stacks root
  • Backup & restore Compose projects — definition + named-volume data into one ZIP on a mounted path or S3, restorable to any host
  • Clone & move projects between hosts — image + volume data + definition; a move removes the source only after the target verifies healthy
  • Terminals — an SSH shell on the Docker host, and exec shells inside containers (both xterm.js, both fully audited)
  • Image cleanup — scheduled image prune sweeps with a dry-run preview to reclaim what auto-updates leave behind
Proxmox

A Proxmox page auto-discovers each node with its LXCs and VMs and monitors pending package updates one layer below Docker. New guests appear within minutes. Per guest: start/stop, resource stats, backups, restore, clone and snapshot rollback, an LXC console and a noVNC VM console, plus apt dist-upgrade from the UI. Hybrid transport — the Proxmox REST API (PVEAPIToken) for inventory and node updates, SSH for per-LXC update counts.

Notifications & integrations
  • Channels — email (SMTP configured in the UI, no redeploy), Telegram, Apprise (Discord, ntfy, Gotify, Slack, webhooks) and web push to your devices, each with per-source toggles and throttling
  • Home Assistant via MQTT — auto-discovered entities for container/guest state, image updates, service health, pending-update counts, per-node alert verdicts, backup freshness and estate roll-ups
  • Prometheus /metrics — the same derived signals as Prometheus gauges for Grafana, authenticated by a personal access token scoped to metrics and served from a 30 s cached snapshot (zero extra load on your hosts)
  • Graylog — optional GELF/UDP shipping of Warning+ logs; off unless a host is set
Accounts & platform

Multi-user JWT auth with optional TOTP two-factor and optional OIDC / SSO (Authentik, Authelia, Keycloak — Authorization Code + PKCE, configured in the UI), scoped personal access tokens, rotating refresh tokens with reuse detection, per-user JSON backup export/import covering the full schema, and an installable PWA with offline app-shell and drag-and-drop custom card ordering.


Security — read before exposing it

Stashboard is built to run your infrastructure, not just display it. Depending on what you enable it can hold the Docker socket (effectively root on the host), open shells on hosts and inside containers, and run destructive Proxmox operations.

  • Never publish it straight to the internet. Put it behind a reverse proxy (Caddy, Traefik, nginx) or a private tunnel (Cloudflare Tunnel, Tailscale, WireGuard) that terminates TLS and adds a second, independent auth layer. The app speaks plain HTTP internally and does not force an HTTPS redirect — that is correct behind a proxy. (HTTPS is also what unlocks PWA install + web push.)
  • The Docker socket mount is optional and commented out in the compose file. Read-only (:ro) is enough for tracking, inspect, logs and stats — Stashboard never mutates under :ro. A writable mount is required only for Update now.
  • Every remote-execution feature is off by default and gated twice — a server-wide switch in Settings and a per-connection/per-host opt-in: host terminal, container exec, Proxmox console, container removal, backup/restore, migration, and the destructive Proxmox operations (which add double confirmation). Every session is written to the audit log.
  • Self-registration is off by default. The first account bootstraps the owner; after that register returns 403 until you deliberately re-open it in Settings → Registration.

Tags

TagMeaning
latestnewest release (moves on every release)
X.Y.Z, X.Y, Xsemver tags from a release — pin these for reproducible deploys
edgelatest build from main, ahead of the last release
sha-<commit>immutable single build

Pin a version by setting STASHBOARD_TAG=11.4.1 in .env. Platform: linux/amd64.

Volumes

PathHolds
/app/DataSQLite database + auto-generated secrets (.secrets/) — back this up
/app/wwwroot/uploadsuploaded service logos

Common environment variables

All settings can be overridden with STASHBOARD_-prefixed env vars (__ descends into a section).

VariableDefaultNotes
STASHBOARD_ConnectionStrings__DefaultConnectionData Source=/app/Data/app.dbSQLite file on the data volume
STASHBOARD_Encryption__Keyauto-generatedBase64 32 bytes; an explicit value wins and disables auto-generation
STASHBOARD_Jwt__Secretauto-generated32+ chars
STASHBOARD_Jwt__AccessTokenMinutes15Access-token TTL
STASHBOARD_Jwt__RefreshTokenDays30Refresh-token TTL
STASHBOARD_Email__ProviderLogOnlySmtp for real sending (or configure SMTP entirely in the UI)
STASHBOARD_Graylog__HostSet to enable GELF/UDP log shipping

Migrations are applied by the app on startup. Updating is just docker compose pull && docker compose up -d.


Licensed under the terms in the repository.

Tag summary

Content type

Image

Digest

sha256:14ef9b8a6

Size

150.1 MB

Last updated

about 13 hours ago

docker pull vahac/stashboard