Files
esh-pfi-infrastructure/configs/homepage
vh 2d54fa9160 homepage: pin Toolchain group to Toolchain tab
The task-board compose carries homepage.group=Toolchain. With no
matching entry in settings.yaml's layout: map, homepage placed it
on the default tab (Main) AND it appeared under the Toolchain tab,
producing duplicate cards. Declare the Toolchain group explicitly
with tab: Toolchain so it renders in exactly one place.
2026-04-24 21:57:23 -07:00
..

homepage

Canonical copies of the gethomepage.dev config for the fleet dashboard running on esh-docker-vm (10.0.50.45).

What lives here

File Purpose
settings.yaml Title, theme, background, quick-launch, group layout
services.yaml Manual entries — infra, BMCs, off-Docker endpoints, fleet hubs
bookmarks.yaml External links (UltraSeedbox, etc.)
widgets.yaml Top-of-page widgets (resource panel, search)
docker.yaml Per-host Docker socket providers for label-based auto-discovery
kubernetes.yaml, proxmox.yaml Empty / sample — kept so homepage doesn't warn on startup
custom.css, custom.js Placeholders
.env.example Template for widget secrets (Plex, Jellyfin, eventual Proxmox tokens)

The real .env (with Plex + Jellyfin keys) lives on esh-docker-vm next to the compose file and is gitignored.

Layout convention

settings.yaml drives the group layout:

Monitoring        row x 3   fleet hubs (Beszel, Dozzle, Backrest, Uptime Kuma)
AI Systems        row x 3   GPU inference services (llama-swap, vLLM embed/rerank)
Apps              list      user-facing apps (Gitea, Vaultwarden, Seafile, ...)
Media             list      Plex, Jellyfin
Games             list      Pterodactyl
UltraSeedbox      row x 3   external bookmarks
Infra - ANA       list      Anaheim hardware + hypervisors + BMCs
Infra - NH3       list      NH3 hardware + hypervisors
Infra - ESH       list      ESH home-lab hardware + hypervisors
Service Networking collapsed  toolchain (Traefik, CrowdSec, Dockge, AdGuard, MQTT)
  • Manual entries (this file) cover things without a Docker label: firewalls, switches, NAS web UIs, BMCs, hypervisors, and the cross-site hubs where direct IP:port URLs are stable.
  • Docker-labeled stacks auto-populate their group via the providers in docker.yaml. To drop a new service into a group, add homepage.group=<group> (plus .name, .icon, .description, .href) labels to its compose file and redeploy.

Placement rule (for new entries)

When deciding where a service lands, ask function first:

  1. Does it watch or back up the fleet? -> Monitoring
  2. Is it an inference / model service? -> AI Systems
  3. Is it a user-facing app? -> Apps
  4. Is it media / games? -> Media or Games
  5. Is it a piece of hardware or a hypervisor? -> Infra - <site>
  6. Is it toolchain / plumbing (no human interaction on the golden path)? -> Service Networking

Site-specific sub-grouping is only used for Infra - because the device inventory maps cleanly to physical sites. App groups are function-only.

Deploying changes

These files are the canonical source for the homepage config. The homepage compose file itself lives on esh-docker-vm (not yet tracked in this repo as a stack), so the usual scripts/deploy-stack.sh flow doesn't apply here yet.

Current workflow — push this directory onto the host:

rsync -av --delete \
  --exclude='.env' --exclude='.env.*' \
  configs/homepage/ esh-docker-vm:/opt/docker/conf/homepage/

The real .env lives on esh-docker-vm next to the compose file and must not be overwritten (holds Plex/Jellyfin keys).

The homepage container reloads most files on-change; if a new group in settings.yaml doesn't show up, docker compose restart on the host.

Follow-up: once the homepage compose file is pulled into stacks/homepage/compose.yaml, move these files to stacks/homepage/conf/ and drop this ad-hoc rsync in favor of scripts/deploy-stack.sh.

Secrets / env substitution

Any config can reference {{HOMEPAGE_VAR_NAME}} and homepage will substitute from the container env at render time. Current uses:

  • HOMEPAGE_VAR_PLEX_KEY (services.yaml -> Plex widget)
  • HOMEPAGE_VAR_JELLYFIN_KEY (services.yaml -> Jellyfin widget)

Keep these out of the tracked YAML; only .env.example ships the names.