Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.4 KiB
felhom.eu — task reports
Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md.
REPORT — Configuration-tab move + online setup command + vmid auto-detect (hub v0.28.0 / host-install v1.2.0)
Date: 2026-07-01 · Repo: felhom.eu (hub/ + scripts/ + manifests/)
Three operator-requested improvements.
Baselines
hub v0.27.0 @ 54daaf9 → v0.28.0; scripts/felhom-host-install.sh v1.1.0 → v1.2.0.
Trunk-based main. Commits: 562c0df (Parts A/B/C code), 629196c (hub image manifest), b77df3c
(script header version).
Part A — global settings moved to the Configuration tab
The two global cards ("Managed updates — global floor", "Day-0 artifacts — agent & golden") were on the Customers page; they now live on Configuration.
internal/web/server.go—handleConfigurationsuppliesGlobalFloor+Artifacts+CSRFField; the two POST routes moved to/configuration/global-floor+/configuration/artifacts.internal/web/configs.go—handleSetGlobalFloor/handleSetArtifactsredirects/configs?flash=…→/configuration?flash=…(5 redirects);handleConfigListdata trimmed to{Customers, ActiveNav, Flash}(dropped the now-unusedGlobalFloor/Artifacts/CSRFField;globalFloorstill computed for per-customer effective-floor).templates/configuration.html— the two cards + their 5 flash banners added.templates/configs.html— cards + flashes removed; back to customer list + "Add Customer".internal/web/render_test.go— updated: asserts the global cards are gone from configs.html and present (with/configuration/*actions + a flash) on configuration.html.
Part B — online setup command + serving fix + passphrase hardening
- B1 (
scripts/…):read_passphrasenow readsread -rsp … < /dev/tty— the no-echo prompt works whether the script is a local file or piped to bash.--passphrase-fileunchanged; passphrase still never on argv/logs/state. - B2 (serving):
https://felhom.eu/scripts/felhom-host-install.shwas 404 — the webpage nginx doc-root is.../current/websiteand git-sync only synced/website/. Fixed inmanifests/webpage.yaml: added/scripts/to the git-sync sparse-checkout + an nginxlocation /scripts/ { root .../current; default_type text/plain; }. Single source of truth (the repo's/scripts), no duplicated copy. Now 200 (verified live, servesSCRIPT_VERSION="1.2.0"). - B3 (
customer_unified.html): new "Option 1: Online install (recommended)" — download-then-run (curl -fsSL … -o … && sudo bash … --customer-id {{.CustomerID}}) with a copy button; the passphrase is not templated (entered at the prompt). Former local-file command demoted to Option 2, debug curl to Option 3. Rationale note: fetched over TLS, inspect-before-run — notcurl | sudo bash.
Part C — vmid auto-detect (scripts/…)
- New
VMID_EXPLICITflag (set by--vmid). The pre-flight guard now determines "in use" against thepct list+qm listid-set (LXC + VMs share the space) via new helpersused_vmids/_vmid_in_use/next_free_vmid. - explicit
--vmid+ in use → deterministic: die unless--force. - default 9201 + in use + no
--force→ auto-pick the next free id (scan upward) + confirm from/dev/tty([y/N]);die "no free vmid confirmed"on decline. Never silent. - default 9201 +
--force→ destructive over-provision, no prompt. --vmidhelp +usage()range updated (and usage now reaches-h, --help).
Green gates
- Hub:
go build ./... && go vet ./... && go test ./...— allok(incl. the updatedTestTemplates_FloorRender). - Script:
bash -nclean.shellcheck(koalaman container on the build server): my additions clean; the only output is 2 pre-existing SC2015 info notices (lines 833/843, unrelated verify functions — present in HEAD, not touched). Local unit test ofnext_free_vmid(3 cases) passes.
Deploy
hub image :0.28.0 built+pushed on 180; manifests/hub.yaml bumped; ArgoCD felhom synced →
Synced/Healthy; deploy/hub on :0.28.0. felhom-webpage rollout-restarted so it re-clones with
the new sparse-checkout (/scripts/) + new nginx config.
Live proofs
- Part A (claude-in-chrome, operator-authed): Configuration tab shows both cards with current values
(global floor v0.87.0; agent 0.43.0 / golden 0.85.1); "Save global floor" →
/configuration?flash=floor_setwith the green "Controller-version floor saved." banner (persist + flash on Configuration). The Customers page shows only the customer list + "Add Customer" (cards gone; footer0.28.0). - Part B (curl + browser):
curl https://felhom.eu/scripts/felhom-host-install.sh→ HTTP 200, servesSCRIPT_VERSION="1.2.0". The customer page (demo-felhom) shows Option 1 online install with the id filled + copy button, Option 2 local, Option 3 debug — passphrase not in Option 1. - Part C (SSH, felhom-pve): the deployed script's own vmid functions against real
pct+qm: used-set{9000,9001,9100,9201,9999}, 9201 in use →next_free_vmid=9202 (verified genuinely free). The actual guard block (extracted from the served script): explicit+no-force → deterministic die; default+no-force → logs "next free vmid is 9202" + prompts on/dev/tty→ cleandie "no free vmid confirmed"on no-confirm; default+--force→ destructive-over-provision warning, no prompt. (A fully interactive real run isn't automatable now that both prompts read/dev/tty; the guard was proven with real host state + the real code path.)
Observations
- The
/dev/ttyreads make the script prompts unattended-proof by design — so an automated run past the prompts isn't possible; Part C was proven via the real functions/guard against livepct+qm. - shellcheck shows 2 pre-existing SC2015 info notices unrelated to this change (left untouched — fixing them would alter unrelated verify logic).
- The customer page still renders the retrieval passphrase in the debug Option 3 + the credential box (pre-existing); the new Option 1 deliberately does not.
Remaining audit follow-ups (unchanged)
Controller-side geo intent sync; a read-only reported-vs-desired "Show Diff"; the cosmetic controllerURL
cleanup in configs.go.