Files
esh-pfi-infrastructure/configs/homepage/README.md
T
vh f4a5ba7c31 feat(booth): add The Booth — ephemeral media drop board for CC sessions
A standing user-level web server (nh3-dev :8090) that renders drop-folders
under ~/booth-data as ephemeral media "booths" so Claude Code sessions can
surface A/B renders and smoke results to the operator, then let them self-wipe.

- Scan-and-serve model, no database, no upload API — a booth is just a folder.
  A folder's own index.html is served verbatim; otherwise an auto-gallery of
  images / webm+mp4 video / audio is rendered, with <file>.txt caption sidecars
  folded in (labels A/B pairs).
- 24h TTL from newest mtime in the tree; background sweeper wipes stale booths.
- Path-traversal + symlink-escape guarded; delete via UI button or DELETE API.
- FastAPI + Jinja2, runs from the checkout under systemctl --user (booth.service),
  alongside the other nh3-dev fleet sidecars. 15 tests, all green.
- Homepage tile added (Apps -> The Booth, siteMonitor /healthz).
- Harden the homepage rsync doc: exclude *.bak* and logs/ so --delete can't
  wipe the host's dated services.yaml backups (footgun found deploying this).
2026-07-20 10:17:40 -07:00

119 lines
5.2 KiB
Markdown

# homepage
Canonical copies of the [gethomepage.dev](https://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, 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? -> the matching `AI - <role>` group
(Inference / Eval & Retrieval / Gateways & Chat / Speech (TTS) /
Audio Tools / Image & Media); a stopped-but-kept stack -> `AI - Dormant`
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 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:
```bash
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).
> **`--delete` footgun (learned 2026-07-20):** the host keeps dated
> `services.yaml.bak-*` safety copies and a live `logs/` dir that are *not*
> in this repo. A bare `--delete` rsync wipes both. The `--exclude='*.bak*'`
> and `--exclude='logs/'` above protect them. For a one-file tweak, skip
> `--delete` entirely 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.