wanderer: ghcr.io/flomp/wanderer:0.16.0 is a ghost - upstream split the app into web+db images, moved registry and renamed the org. Restructured to upstream's own v0.20.0 compose (3 services, new /data/plugins volume, second public hostname for PocketBase, meilisearch pinned DOWN to upstream's v1.36.0 per the R-42 ruling). plant-it: retired. The repo name was wrong (plant-it-server) but upstream has DELETED self-hosting; last server image is 2024-12-10 and it needs MySQL+Redis the template never had. Moved to retired/ rather than deleted - reversible. R-41 slice 1: check-image-resolvable.py. Encodes two traps - manifest inspect exits 0 while printing toomanyrequests, and the inverse, where the first sweep called 24 of 65 pins dead because Hub throttled it. Ambiguity is INCONCLUSIVE, never an accusation.
2.7 KiB
CLAUDE.md — app-catalog-felhom.eu
Loads when Claude Code touches this repo. Current state:
CONTEXT.md+CHANGELOG.mdtop. Cross-repo orientation: workspace-root/mnt/5_hdd/felhom.eu/git/CLAUDE.md.
What this repo is
The Felhom app catalog: one directory per app under templates/<app>/, each holding exactly
docker-compose.yml + .felhom.yml (deploy fields, resources, healthcheck probe, app_info — all
customer-facing text in Hungarian). The felhom-controller git-syncs these to every customer box;
.felhom.yml drives the deploy wizard. templates.json + scripts/generate-customer.sh are LEGACY
(Portainer-era) — new apps don't touch them.
Deploy contract
Push to main = deploy. The controller's sync picks changes up within 15 minutes (or trigger via
the dashboard "Sablonok frissítése" button / POST /api/sync). Only the two template files sync;
deployed app.yaml (customer secrets) is never overwritten. Full deploy details: the
felhom-build-deploy skill.
Conventions
- See
REUSE.mdbefore adding or editing an app — canonical example app (paperless-ngx), required.felhom.ymlfields, healthcheck family per image type, memory-limit rules, traps. - Update
REUSE.mdin the same commit that changes a catalog-wide convention. README.mdis the format spec — update its app tables when adding an app.- Update
CHANGELOG.md(newest on top) and overwriteREPORT.mdwith every pushed change. - No secrets in any committed file; secrets are generated at deploy time via
deploy_fieldsgenerate:specs. - Never
:latestor untagged images in templates — pin a concrete version tag; an app deployed anywhere in the fleet is pinned to the digest it is currently running (a pin must never cause a version jump). Digest pins (@sha256:) also count. Gate:python scripts/check-image-pins.py(run after any compose change; exit 1 on any floating/missing tag). - A pinned tag can still rot away upstream — the pin gate is syntactic and cannot see that.
Second gate:
python3 scripts/check-image-resolvable.py(exit 0 resolve / 1 GONE / 2 inconclusive), run at the start of every catalog campaign and before any publish train that vouches the catalog. Needs network +docker; unauthenticated Docker Hub throttles a full sweep, sodocker loginfirst or expect exit 2. It reports a throttle as INCONCLUSIVE, never as a dead image. - Retiring an app:
git mv templates/<app> retired/<app>(seeretired/README.md) — the sync discovers apps by directory, so this un-offers it while keeping it revivable. Sync never removes a stack dir it already copied, so retirement freezes the app on existing boxes rather than deleting it.