Six PFI VMs/LXCs previously known only via proxmox_inspect.sh —
covered by vzdump but not in servers/, so operational context
(roles, backup posture, ssh target) was missing:
pfi-ana-webhost (VMID 110) — web workload
ana-filebot (LXC 112) — file-task automation
pfi-pteradactyl (VMID 107) — Pterodactyl game panel
pfi-tacticalrmm (VMID 111) — TacticalRMM remote-management
pfi-postgres (VMID 105) — shared Postgres (vaultwarden/gitea/
paperless backends)
ana-wg (LXC 113) — WireGuard VPN gateway
Plus three SureFire tenant hosts at the Anaheim colo:
sfsrv-ana — tenant Proxmox hypervisor (10.250.250.115:8006)
sf-ana-container — container workload on that Proxmox
sf-r630 — physical R630 (iDRAC 10.250.250.110 for PFI-side
hardware mgmt; OS is tenant-scoped)
Each server dir has README + ssh-target where applicable. SureFire
entries explicitly document tenancy scope: PFI provides hosting,
SureFire owns the OS; management actions need tenant coordination.
SureFire hosts have no ssh-target by default.
Homepage Infra - ANA gains two new cards:
- SFsrv-ANA (https://10.250.250.115:8006, si-proxmox icon)
- SF-R630-iDRAC (https://10.250.250.110, si-dell icon)
PFI-ANA-ML2 BMC gained an href since it has a usable web UI.
CLAUDE.md fleet table extended with all 9 new rows. Placement-rules
section notes the SureFire tenant boundary.
Memory: new project_surefire_tenant.md so future sessions know sf-*
hosts are tenant-scoped by default.
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, 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? ->
AI Systems - 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 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.