Operator-directed (Vuong 2026-08-13): migrated stonehenge-park off the nh3-docker beta deployment to a permanent fixture on ana-docker (10.250.50.70) before the v1.0.0 final cut. SQLite (park-data) migrated consistently (stop -> tar-copy -> start; byte-identical). restic auto-covered by ana-docker's /var/lib/docker/volumes source. Stable name park.phasefinal.com -> 10.250.50.70 (Cloudflare DNS-only) so clients decouple from the host IP. Homepage tile 'The Henge' added. nh3-docker stack left stopped as rollback pending park-dev cutover verification.
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 across four tabs:
tab: Main
Notes / News / Monitoring / Apps / Media / Games / UltraSeedbox
tab: AI (the inference fleet, sorted by role)
AI - Inference LLM seats you call (gen, char-rp, char-rp-reasoning, summarizer)
AI - Eval & Retrieval judges, reward, rerank, embed, image-quality
AI - Gateways & Chat routing gateway, control plane, chat frontends
AI - Speech (TTS) text-to-speech engines
AI - Audio Tools speech-to-text + audio dataset tooling
AI - Image & Media image/video generation + pipelines
AI - Dormant stopped stacks (rollback seats, retired auditions)
tab: Infrastructure
Infra - ANA / NH3 / IRV / ESH hardware + hypervisors + BMCs, per site
tab: Toolchain
Service Networking / Toolchain plumbing, rarely clicked
The AI tab replaced the old single flat AI Systems group (2026-07-14): a
20+ service list read as one endless column, so it was split by function.
Group membership is the homepage.group=AI - <role> label on each compose
file; a label change only takes effect when the container is recreated
(docker compose up -d <svc>, or up --no-start <svc> to relabel a stopped
stack without starting it).
- 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, addhomepage.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:
- Does it watch or back up the fleet? ->
Monitoring - Is it an inference / model service? -> the matching
AI - <role>group (Inference / Eval & Retrieval / Gateways & Chat / Speech (TTS) / Audio Tools / Image & Media); a stopped-but-kept stack ->AI - Dormant - Is it a user-facing app? ->
Apps - Is it media / games? ->
MediaorGames - Is it a piece of hardware or a hypervisor? ->
Infra - <site> - Is it toolchain / plumbing (no human interaction on the golden path)? ->
Service Networking
Site-specific sub-grouping is used for Infra - (device inventory maps to
physical sites) and role-based sub-grouping for AI - (the fleet is large
enough to warrant it). Other 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.*' \
--exclude='*.bak*' --exclude='logs/' \
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).
--deletefootgun (learned 2026-07-20): the host keeps datedservices.yaml.bak-*safety copies and a livelogs/dir that are not in this repo. A bare--deletersync wipes both. The--exclude='*.bak*'and--exclude='logs/'above protect them. For a one-file tweak, skip--deleteentirely and push the single file:rsync -av configs/homepage/services.yaml esh-docker-vm:/opt/docker/conf/homepage/services.yaml(back up the host copy first:ssh esh-docker-vm 'cp -a …/services.yaml …/services.yaml.bak-<date>-<what>').
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.