Files
felhom.eu/REPORT.md
T
admin 89a2e508a7 scripts: felhom-host-install.sh v1.0.0 — Day-0 host bootstrap (live-validated)
Operator-run Day-0 automation for a fresh PVE host: pveum token -> hub
POST /host-enroll (single secret, option C) -> agent config -> felhom-agent
--selftest=provision -> verify. Idempotent/resumable (state.json), --dry-run,
--resume, --force, --preserve-from; --mode dr is a documented 10D stub.

Live-validated on felhom-pve: authorized wipe of demo guest 9201 + full
re-provision from the golden -> controller config-pull + public tunnel HTTP 200
+ host-report of 9201; idempotent --resume no-op. Found+fixed one ordering bug
during the run (token ACL must be applied AFTER token rotation — token-remove
purges the ACL).

Adds scripts/README.md (operator runbook) + scripts/CHANGELOG.md; REPORT
overwritten; spike doc pointer added. No service code changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TtXesNa2LGbMmE4DNL6SE7
2026-06-26 20:04:25 +02:00

7.2 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.


Day-0 host-bootstrap script — built + live wipe-and-provision test — 2026-06-26

Task: Deliver scripts/felhom-host-install.sh (operator-run Day-0 bootstrap) and validate it with an operator-authorized destructive live test: wipe demo guest 9201 and re-provision it from scratch via the script. Single repo (felhom.eu, new scripts/).

Confirmed baselines

  • hub 1539746 v0.14.0 (/host-enroll option C, just shipped) · felhom-agent 4725396 v0.41.0 (--selftest=provision) · felhom-controller e0cf78b v0.84.0.
  • Live host felhom-pve (192.168.0.162): PVE 9.2.2, node demo-felhom, agent v0.41.0 at /root/.config/felhom-agent/agent.json (systemd unit -config path — not /etc/felhom-agent/), golden local:backup/vzdump-lxc-9100-2026_06_23-16_38_49.tar.zst (rootfs 32 / docker 16 / sysdata 8 GiB base).

Deliverable

  • scripts/felhom-host-install.sh v1.0.0 — 7 idempotent/resumable steps (pre-flight → pveum token → grows → host-enroll → agent config → provision → verify), single-secret (passphrase no-echo/0600 file), --dry-run/--resume/--force/--preserve-from, --mode dr documented stub.
  • scripts/README.md (operator runbook), scripts/CHANGELOG.md (v1.0.0).
  • documentation/audits/SPIKE-…-2026-06-26.md — pointer added (script ships the gap inventory).
  • bash -n passes (Windows + host). shellcheck unavailable on dev box, build box, and felhom-pve — not run.

Live supervised test (felhom-pve, customer demo-felhom, authorized destructive)

Passphrase sourced operator-side from the hub DB into a 0600 file on the host (never printed); deleted (shredded) after. Methods noted per check.

A. Pre-wipe snapshot: saved pct config 9201, controller 0.84.0 Up (healthy), agent.json.bak (1574 B), token list. Confirmed demo-felhom host exists in hub (demo-felhom-01, plus two stale dr-drill-host* cruft rows — demo-felhom-01 has today's updated_at, so GetHostByCustomer returns it).

B. Wipe (authorized): pct stop 9201 + pct destroy 9201 --purge (all 3 volumes removed); moved agent.json + cleared state to simulate a fresh host.

C. Dry-run: every mutating command printed correctly — pveum role-modify (16 privs), both ACL lines, token rotate, enroll curl, agent.json write, provision call. Pre-flight green (golden auto-found, passphrase valid, vmid free).

D. Real run — found + fixed a bug, then SUCCESS:

  • Bug found live: first run failed the post-config agent selftest with HTTP 403 … missing privilege Sys.Audit. Root cause: the script applied the token ACL before rotating the token, and pveum user token remove purges the token's ACL — so the new token had no ACL. Fix: apply both ACL grants after the token is (re)created. (scripts/felhom-host-install.sh step 2.)
  • Re-run green: token rotated (old config token failed selftest → rotate → ACL → selftest passed); host-enroll200 REUSE of demo-felhom-01 (idempotency confirmed); agent.json written 0600 + read-only selftest passed + daemon restarted; provision front-half bring-up (1m11s) + back-half bootstrap mount mp9/etc/felhom-bootstrap + local-api token minted; guest 9201 running, onboot:1, layout rootfs 32G / mp0 200G / mp1 50G / mp8 bind — exactly the standard appliance.

E. Verify (method per check):

Check Method Result
guest running + onboot:1 + volumes pct status/config running, onboot 1, 32/200/50G + mp8 bind
controller healthy pct exec docker ps Up (healthy), image felhom-controller:0.77.0 (from golden)
controller pulled config from hub controller logs (pct exec) bootstrap: pulled config from hub for demo-felhom, merged local_api … coming up configured; Hub connectivity … HTTP 200
serving pct exec curl :80 HTTP 301 (traefik)
Cloudflare tunnel connected cloudflared logs 4 Registered tunnel connection (vie06, bud01)
public URL curl from build box (public DNS) felhom.demo-felhom.eu → HTTP 200 via Cloudflare 188.114.97.11 (ingress *.demo-felhom.eu → traefik)
real dashboard curl public <title>Vezérlőpult — Felhom.eu</title>
host-report includes guest 9201 hub sqlite demo-felhom-01/9201 status running, last_seen current
storage plane (functional touch) pct exec ls /mnt/felhom-drives bound, felhom-flash + felhom-usb visible (data intact); local-api drive plane reachable

Public URL returned 000 from felhom-pve and the Windows dev box — split-horizon (the agent's LAN resolver points *.demo-felhom.eu at the guest's LAN IP, which serves :80 not :443). Through the Cloudflare edge (build box) it is 200. Not a provision fault.

F. Idempotency: plain re-run refused to clobber the live 9201 (exit 1, "pass --force"); --resume re-run skipped token/grows/enroll/agent_config/provision → verify-only no-op, token not rotated (selftest still passes), guest not re-provisioned.

G. Cleanup: passphrase file shredded; agent.json.bak + snapshot retained; final state — 9201 running, host_id demo-felhom-01, agent active.

pveum / token automation result

Role FelhomAgent normalised to the authoritative 16 privileges (incl. Sys.Audit, SDN.Use); user felhom-agent@pve; privsep token rotated; both ACL grants (user and token) applied after token creation. Read-only felhom-agent --selftest passed against the live API with the minted token.

Observations (out-of-scope — not acted on)

  1. -hub-password on argv: the agent's only input for the retrieval passphrase during provision is the -hub-password flag → briefly visible in ps during --selftest=provision. Candidate agent follow-up: accept it via env/stdin. (Not fixed here — would modify the agent.)
  2. Golden freshness: the golden bakes controller 0.77.0; the freshly provisioned demo runs 0.77.0 (pre-wipe was 0.84.0, and the v0.78.0 drive-register stable-path fix is newer than the golden). Rebuild the golden at the current controller for parity; full drive re-enroll via the UI needs controller ≥0.78.0. The Day-0 script itself is version-agnostic.
  3. Multi-host cruft: demo-felhom carries two stale dr-drill-host* rows. GetHostByCustomer (most-recent-updated) correctly returned demo-felhom-01 here, but the Day-0 invariant is one host per customer — drill artifacts should be cleaned up (left untouched; out of scope).
  4. Serving + binary/golden delivery: the script lives in scripts/; serving it at https://felhom.eu/scripts/…, plus agent-binary and golden central delivery, are documented productionization hooks (the test used the local binary + golden).

Commits

  • <this commit> — script v1.0.0 + scripts/README + scripts/CHANGELOG + spike pointer + REPORT.

No secrets in any committed file. PVE-token secret + host api_key live only in the host's 0600 agent config.