Skip to content
MaxDeavyPublic

About

Homelab Dashboard mit vielen Funktionen, alles über das Webinterface

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

51 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Homelab Dashboard

Homelab Dashboard

Self-hosted dashboard for homelab services — configure everything in the browser, no YAML. Tiles with health checks, live API data on hover, and a layout you can shape to your setup.

Deutsche Version: README_de.md

Features

Dashboard at a glance

Your services as tiles in category columns with a glass-style UI. Each tile can show a health status via a separate check URL.

Theme presets (Stealth, Ember, Neon, Cobalt) or custom colors, dark/light mode, background image and color, logo upload — adjustable tile, window, and page width.

Live API hover widgets (46+ services)

Hover a service tile for real-time API data: Plex, Proxmox, Pi-hole, qBittorrent, Home Assistant, FRITZ!Box, and more. Credentials are stored AES-256-GCM encrypted in SQLite.

Hold Shift and click field labels to show or hide individual widget rows — per service, stored in the database (logged-in admins only). Now Playing / Watching Now appear only during active playback.

Includes Jellyfin, Plex, Nextcloud, Immich, *arr stack, Docker/Portainer, NPM, Proxmox, QNAP, Navidrome, Kavita, n8n, Grafana, Uptime Kuma, Vaultwarden, Gitea, Syncthing, Authentik, FreshRSS, BookStack, Frigate, Autobrr, Romm, Trilium, and others — see the widget table below.

Layout & pages

  • Multiple dashboard pages with tabs and keyboard shortcuts 1–9
  • Drag & drop categories and tiles (hold Shift on the dashboard when logged in)
  • Up to three services per row — in admin or on the dashboard
  • Web / LAN toggle per service: external URL vs. local IP/hostname in the header (can be disabled)

Keyboard shortcuts

Available on the dashboard and in admin (not while typing in a field):

Key Action
D Open dashboard
S / E Open settings (admin)
1–9 Switch page (first nine)
. Toggle light / dark mode
W Toggle Web / LAN mode (when LAN is enabled)
L Switch language (EN / DE)
T Hide services without LAN URL (when LAN is enabled)
Shift Layout mode — drag & drop categories, tiles, and links (logged-in admins)

Light/dark, Web/LAN, and hide-without-LAN preferences are stored in the browser (localStorage). The full list is also shown under Admin → Settings.

Backup & restore as ZIP (database + uploads + encrypted widget credentials). Optional dashboard sign-in so only authenticated users see the board.

Found a bug or missing API field for your setup? Please open an issue — I only run about half of the widgets myself.

Quick start

Requirements

Node.js 20+ & npm
or
Docker

Local (development)

cp .env.example .env
# Set ADMIN_PASSWORD and SESSION_SECRET in .env

npm install
npm run db:migrate
npm run dev
URL Description
http://localhost:3000 Dashboard
http://localhost:3000/admin Admin (login with ADMIN_PASSWORD)

Docker

Pre-built image (recommended)

No local build required — pull from GitHub Container Registry.

mkdir homelab-dashboard && cd homelab-dashboard

Create docker-compose.yml:

services:
  dashboard:
    container_name: homelab-dashboard
    image: ghcr.io/maxdeavy/dashboard:latest
    restart: unless-stopped
    ports:
      - "${PORT:-3333}:${PORT:-3333}"
    env_file:
      - .env
    environment:
      PORT: ${PORT:-3333}
    volumes:
      - ./data:/app/data

Create .env (adjust values before starting):

ADMIN_PASSWORD=change-me
SESSION_SECRET=change-me-to-a-random-string-at-least-32-characters
PORT=3333
# Behind a reverse proxy (HTTPS):
# APP_URL=https://dashboard.example.com
# COOKIE_SECURE=true
docker compose pull
docker compose up -d

Dashboard: http://localhost:3333 (or the PORT set in .env)

Docker CLI only (without Compose):

mkdir homelab-dashboard && cd homelab-dashboard

Create .env as above, then:

docker pull ghcr.io/maxdeavy/dashboard:1.0.5
docker run -d \
  --name homelab-dashboard \
  --restart unless-stopped \
  -p 3333:3333 \
  --env-file .env \
  -v "$(pwd)/data:/app/data" \
  ghcr.io/maxdeavy/dashboard:1.0.5

Available versions: GitHub Releases
Image tag matches the release version (v1.0.5 → ghcr.io/maxdeavy/dashboard:1.0.5). The latest tag always points to the most recent release.

Build from source (development)

cp .env.example .env
# Set PORT=3333 and production secrets

docker compose up -d --build

The SQLite database lives in the ./data volume. Migrations run automatically on container start.


Configuration

All settings are managed in the admin at /admin. The last opened tab is remembered in the browser.

Services

Feature Description
Web URL / LAN URL External address and optional local IP/hostname
Active / inactive Disabled services are hidden
Icons Presets from assets/, custom URL, or upload
Tile color Individual accent color
Health check Optional separate URL; per-service TLS exception
Hover widget API integration with encrypted credentials
Link target Same tab or new tab
Row layout Arrange up to three services side by side per row

Unsaved changes in service or category dialogs trigger a confirmation before closing.

Arrange services in rows

In Admin under Services, the default view is still one full-width row per service. Via drag & drop you can also place services side by side or between existing tiles — up to three per row. The layout is saved automatically and reflected on the dashboard.

Action How
Own row Drag onto the line above a row
Beside another Drag onto the vertical line to the right of a tile
Between two Drag onto the vertical line between two tiles
New row at bottom Drag below the last row in the category

Single services keep full width — only deliberately grouped tiles sit side by side.

Display on the dashboard

Layout Appearance
1 per row Standard tile: icon left, name and subtitle
2 per row Compact tiles with spacing, uniform row height
3 per row Icon on top, subtitle below (no service name), uniform row height

Logged-in admins can also adjust layout on the dashboard with Shift + drag & drop (horizontal and vertical insertion lines, same as in admin).

The selected services page in the admin is remembered in the browser.

Pages

Multiple dashboard pages with their own categories. Switch in the dashboard via the tab bar or keys 1–9.

Keyboard shortcuts

See the keyboard shortcuts table in Features. Preferences for light/dark, Web/LAN, and hiding services without a LAN URL are saved per browser.

Design (Settings)

  • Theme presets (Stealth, Ember, Neon, Cobalt) or custom colors
  • Dark / light mode
  • Background image, background color, and logo
  • Layout sliders: icon size, tile shape, font, column spacing, max width
  • Language — English or German (stored in a cookie, applies to dashboard and admin)

Web / LAN

Mode Behavior
Web Always uses the Web URL
LAN Uses lanUrl when set; otherwise dimmed tile with hint

You can optionally hide services without a LAN URL entirely in LAN mode (Admin → Settings or key T on the dashboard).

The selection persists after reload (localStorage). The Web/LAN toggle can be hidden in Admin → Settings if you do not need LAN URLs.

Customize widget fields

With a widget panel open, hold Shift and click a field label to hide or show it. The selection is stored per service in the database and applies on every device (logged-in admins only). In Shift mode, hidden fields appear struck through so you can restore them.

Edit layout (dashboard)

  1. Hold Shift
  2. Drag categories (⋮⋮ handle) and tiles to reorder
  3. Release Shift — normal navigation resumes

While dragging tiles, insertion lines appear: horizontal between rows, vertical between or beside tiles in a row. Only for logged-in admins; disabled while a search is active.

Backup

In Admin under Settings: export or import a ZIP backup (database and uploads, including encrypted widget credentials).


Widget configuration

In Admin: Services → edit service → Links & widget

Widget Credentials Shows e.g.
Sonarr / Radarr / Lidarr / Bazarr API key Queue, size, missing
Prowlarr API key Indexers, queue
qBittorrent / Transmission / Deluge User + password Speed, active torrents
SABnzbd API key Speed, queue
Proxmox API token + node CPU, RAM, disk, VMs/LXC, uptime
Docker Engine — Containers, images
Portainer API token Containers per endpoint
Nginx Proxy Manager Email + password Online hosts, SSL certs, redirects
Pi-hole / AdGuard Home App password / API key Queries, block rate
Technitium DNS API token Queries, blocklists
Jellyseerr / Overseerr API key Open requests
Jellyfin / Plex / Tautulli API key / token Active streams, library, sessions / stats
Nextcloud NC token Storage, users, apps
Immich API key Library statistics
Mealie API token Recipes
Kavita / Audiobookshelf Auth key / API token Libraries, series, storage / media
Navidrome User + password Artists, albums, now playing
Paperless-ngx API token Documents, inbox
Trilium Notes ETAPI token Notes, attachments, storage
Uptime Kuma API key / status page Monitors up/down, response time
Vaultwarden Admin token Users, organizations
Gitea Access token Repos, issues, pull requests
Syncthing API key Devices, folders, sync traffic
Authentik API token Users, apps, providers
FreshRSS Email + API password Unread, feeds, categories
BookStack API token Shelves, books, pages
Frigate User + password Cameras, detection, events
Autobrr API key Releases, filters, indexers
Romm User + password Platforms, ROMs, storage
WordPress User + application password Posts, pages, comments, media
Open-Meteo — (location) Temperature, wind, precipitation
OpenWeatherMap API key + location Current weather
Cloudflare API token Zones, account, status
DuckDNS / No-IP Token or login Domain, IP
Tailscale API key Devices online/offline
GitHub PAT Repos, notifications
Healthchecks.io API key Checks up/down
Gotify / ntfy / Pushover Token Messages, status
Telegram / Matrix / Discord / Slack Bot token Bot status, channels
UniFi / OPNsense / TrueNAS Login or API key Network, system
Glances / Netdata / Prometheus URL (key optional) CPU, RAM, metrics
OctoPrint / Komga / Shelly Key or login Print, manga, relay
Sentry / AfterShip / HetrixTools API-Key Errors, packages, uptime
Beszel Email + password Systems online/offline, CPU, RAM, disk (color-coded)
Homelab Dashboard API key Remote dashboard stats
n8n / Grafana API key Workflows / dashboards
Home Assistant Access token Entities, automations, or entity state
QNAP User + password CPU, RAM, volume, temperature
FileBrowser User + password Storage usage, shares, version
Guacamole User + password Connections
FRITZ!Box — Connection, speeds, external IP, traffic (TR-064)
Iframe / Embed — External page in hover panel
Generic — HTTP status, latency

API credentials are stored AES-256-GCM encrypted in SQLite.

Public API (v1)

Under Admin → Settings → Security, you can enable a read-only REST API. Other dashboards or scripts can fetch services, health status, and widget data — without the admin password, using an API key only.

  1. Enable Public API (v1) and save
  2. Generate API key (shown once — store it securely)
  3. Send requests with Authorization: Bearer <api-key> or header X-API-Key
Endpoint Content
GET /api/v1 API info and endpoint list
GET /api/v1/dashboard Pages, categories, services, links, stats
GET /api/v1/services All services incl. health
GET /api/v1/health Health checks
GET /api/v1/widgets/{id} Widget data for a service

Widget credentials and encrypted secrets are never exported. Use widget type Homelab Dashboard to display data from another instance with API v1 enabled.

When Dashboard requires sign-in is enabled, internal read APIs (/api/dashboard, /api/health, /api/widgets, …) also accept the Public API key for automation (widget credentials remain session-only).

Docker widget

Talks to the Docker Engine API. docker-compose.yml includes an optional socket mount; docker-socket-proxy is safer:

  1. Enable the proxy in docker-compose.yml (commented template)
  2. Widget type Docker Engine, API URL http://docker-socket-proxy:2375

QNAP

  • User with system monitoring permissions
  • Disable 2FA for the API user
  • API URL e.g. https://nas.local:8080 (QNAP web port)
  • Optional: volume name for a single volume

Environment variables

Copy .env.example to .env. Only a few values are required for a typical deployment.

Required (production)

Variable Description
ADMIN_PASSWORD Admin login (plain text or bcrypt hash via npm run hash-password)
SESSION_SECRET Session encryption (min. 32 characters)

Common

Variable Description Default
PORT HTTP port 3000 (Docker: 3333)
APP_URL Public URL for redirects behind a reverse proxy from request headers
COOKIE_SECURE Send session cookie only over HTTPS false

HOSTNAME (bind address inside the container) defaults to 0.0.0.0 in the Docker image — you do not need to set it in .env. In Compose, environment: overrides .env for the same key anyway.

APP_URL is not the same as HOSTNAME: the app listens on 0.0.0.0:PORT inside Docker, while APP_URL is the address users type in the browser (e.g. https://dashboard.example.com). Set APP_URL only when redirects after login go to the wrong host (typical behind nginx, Traefik, etc.).

Optional (defaults are fine)

Variable Default
CREDENTIALS_ENCRYPTION_SECRET = SESSION_SECRET
CREDENTIALS_ENCRYPTION_SALT homelab-dashboard-salt
SESSION_COOKIE_NAME homelab-dashboard-session
SESSION_MAX_AGE_DAYS 7
DATABASE_URL file:./data/dashboard.db
APP_STORAGE_PREFIX / NEXT_PUBLIC_APP_STORAGE_PREFIX homelab-dashboard
MAX_BACKGROUND_UPLOAD_MB 5
MAX_LOGO_UPLOAD_MB 1
MAX_ICON_UPLOAD_MB 1

Cookie name and storage prefix only matter if you run multiple instances on the same browser origin or need to migrate sessions — not for a normal single install.

In production, ADMIN_PASSWORD and SESSION_SECRET must be set.

For a bcrypt hash instead of plain text:

npm run hash-password -- "your-strong-password"

Put the output into ADMIN_PASSWORD in .env.

Migrations run automatically when the server starts (instrumentation.ts). npm run db:migrate is optional for manual runs.

See SECURITY.md for deployment guidance.

Self-signed TLS certificates: enable per service in Admin under Health check.


Icons

Bundled icons live in assets/ and are copied to public/assets/ on build (npm run assets:sync).


Tech stack

  • Next.js 16 (App Router), React 19, Tailwind CSS 4
  • next-intl for internationalization
  • SQLite with Drizzle ORM
  • iron-session for admin auth
  • Docker with multi-stage build

Scripts

Command Description
npm run dev Development server
npm run build Production build
npm run start Production server
npm run db:migrate Run database migrations manually
npm run db:generate Generate Drizzle migration
npm run hash-password Generate bcrypt hash for ADMIN_PASSWORD
npm run lint ESLint

Security

  • Set strong values for ADMIN_PASSWORD and SESSION_SECRET in production.
  • Prefer a bcrypt hash for ADMIN_PASSWORD (npm run hash-password).
  • Set COOKIE_SECURE=true behind HTTPS.
  • Enable Dashboard requires sign-in when the instance is reachable beyond trusted networks.
  • Enable Public API (v1) only when needed; treat the API key like a password.
  • Login and failed API key attempts are rate-limited per IP.
  • Widget credentials are encrypted in the DB; still grant only minimal API permissions.
  • Mounting the Docker socket directly is convenient but risky — use a socket proxy.

Details: SECURITY.md


Feedback & issues

Bugs, missing widget data, or feature ideas — please open an issue (service name, widget type, expected vs. actual behavior). See also the note under Features.


License

MIT

About

Homelab Dashboard mit vielen Funktionen, alles über das Webinterface

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages