- JavaScript 45.9%
- TypeScript 32.3%
- CSS 16.6%
- HTML 4.2%
- Shell 0.9%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Publish Container / publish (push) Successful in 24s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
| .forgejo/workflows | ||
| .vscode | ||
| design | ||
| docs | ||
| public | ||
| scripts | ||
| server | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| docker-compose.build.yml | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| homelab-dashboard.code-workspace | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
Homelab Dashboard
A private dashboard for homelab service links, uptime, infrastructure stats, media libraries, storage health, downloads, and operational shortcuts. It polls your services from one backend (so tokens never reach the browser), raises alerts, and has a wall-mounted wallboard view.
The wallboard (/wall) in demo mode with three problems. Blue is normal; red is a problem. More about the wallboard.
The dense view (/) for a work screen: problems stand out, healthy rows stay quiet, and rows expand for detail.
The original card dashboard, still available at /classic, now in the same design language, with cards, drill-downs, layouts and diagnostics. All screenshots use built-in demo data, never real hosts or secrets.
The admin console. Every screen, from sign-in to settings, shares one design language: flat panels, blue for normal, red for problems.
What it monitors
Proxmox, TrueNAS, ASUSTOR and UniFi NAS storage, UniFi Network, Uptime Kuma, qBittorrent, SABnzbd, Plex, Seerr, Kavita, Grimmory and Navidrome, with optional webhook alerts (Discord, ntfy or generic JSON). Each one is set up in the admin page; the Module Setup Guide walks through every module with screenshots and says where to find each URL, token and key.
Documentation
- Module Setup Guide: configure each integration, with screenshots.
- Wallboard: the wall view, the read-only display key, kiosk setup, and TV size and viewing distance.
- Design Language: the visual rules, palette, contrast results, and where the styles live.
- Integrations: protocol and behavior details for each module.
- Nginx proxy, Container registry, Roadmap.
Development
npm install
npm run dev
The Vite dev server handles the frontend. Production runs through the Node backend so API tokens stay server-side.
Build
npm run build
Production
Example docker-compose.yml:
services:
homelab-dashboard:
image: registry.example.com/YOUR-USER/homelab-dashboard:latest
container_name: homelab-dashboard
restart: unless-stopped
environment:
- DATA_DIR=/data
- PORT=3000
# Number of reverse proxies in front of the dashboard (nginx, NPM, ...). Use 1 behind one proxy, 0 when clients connect directly.
- TRUST_PROXY_HOPS=0
security_opt:
- no-new-privileges:true
ports:
- "3000:3000"
volumes:
- homelab-dashboard-data:/data
volumes:
homelab-dashboard-data:
Start or update the container:
docker compose pull
docker compose up -d
The container listens on port 3000. On first launch, open http://YOUR-VM-IP:3000/admin to create the initial admin user.
It is ready to run behind an nginx reverse proxy. See docs/nginx-proxy.md.
Container publishing notes live in docs/container-registry.md.
To build locally instead of using the Forgejo container registry:
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
Deployment Settings
These environment variables control how the server runs. They are not stored in the admin database. See .env.example for the full list.
| Variable | Default | Purpose |
|---|---|---|
TRUST_PROXY_HOPS |
0 |
Number of reverse proxies in front of the dashboard. Set 1 behind nginx so login rate limits and the audit log use the real client IP. Leave 0 if clients connect directly. |
DASHBOARD_SETUP_TOKEN |
unset | When set, creating the first admin user requires this token. |
DASHBOARD_ALLOWED_ORIGINS |
unset | Extra browser origins allowed to make changes, needed only if your proxy rewrites the Host header. |
DASHBOARD_DISPLAY_KEY |
unset | Optional read-only key (24+ characters) that lets a wall display open /wall?key=... without logging in. It only opens the live data connection. See Wallboard. |
DASHBOARD_DEMO |
unset | ok or warn serves synthetic demo data only, for previews and screenshots. Never set on a real deployment. |
DASHBOARD_REALTIME_INTERVAL_MS |
5000 |
Tick interval of the background poller and WebSocket pushes. |
DASHBOARD_POLL_<ID>_SECONDS |
per integration | How long each integration's result is reused, for example DASHBOARD_POLL_STORAGE_SECONDS=300. |
A single server-side loop polls every integration, records history, sends alerts, and pushes updates to all open browsers, so alerts fire even when nobody has the dashboard open and extra browser tabs do not add upstream API calls.
The container runs as the unprivileged node user. On start it fixes ownership of /data for volumes created by older root-run images.
npm run test:hardening runs the regression checks (security hardening, the pollers, the download clients, demo mode and the display key) against throwaway instances. npm run docs:screenshots regenerates every image in docs/ from demo data; it needs Chrome or Edge.
Admin Settings
Open /admin after first launch to create the initial admin user. After registration, use the admin dashboard to configure module URLs and tokens.
The admin dashboard stores the admin user, module settings, notification history, and audit history in a SQLite database at /data/dashboard.db. Existing settings.json, notification-history.json, and audit-log.json files are imported into the database automatically on first startup after upgrade. Secret fields are saved server-side and are not returned to the browser after saving.
The dashboard includes local layout profiles, wallboard presets, mobile-friendly card layouts, theme presets, card drill-downs, a SQLite-backed event timeline, server-side Uptime Kuma and diagnostic history samples with retention controls, module-specific diagnostic guidance, running version visibility, redacted settings export, history export/clear controls, and optional webhook alert notifications. Browser-local items such as layout, theme, uptime ticks, and older fallback timeline data can be cleared from the Dashboard Recovery section.
The admin dashboard also includes a White Label section for changing the header title, subtitle, eyebrow text, logo URL, and module documentation link base URL.
For module-by-module setup, including where to find each URL, API key and token, use the Module Setup Guide. The same guide is mirrored in the Forgejo wiki (Module-Setup), and each module's Wiki setup button opens its page there.
Project Shape
server/server.jsserves the production app, the WebSocket feed and the admin API;server/dashboard-runtime.jsis the background poller; each integration lives in its ownserver/*.jsmodule and returns displaychecksplus structuredstats.server/demo-data.jsproduces the synthetic data for demo mode.src/DenseView.tsx(the default view at/),src/WallBoard.tsx(/wall) andsrc/App.tsx(the classic dashboard at/classic, the admin console and routing) are the views.src/normalize.tsandsrc/stats.tsturn API data into typed shapes, andsrc/useDashboardFeed.tsis the live WebSocket feed.scripts/hardening-smoke.mjsholds the regression checks, andscripts/capture-screenshots.mjsregenerates the documentation images.docs/has the guides,CHANGELOG.mdlists what changed in each release, anddesign/keeps the original mockups.





