Doc-only spike (no hub code change). Validated on demo-felhom (guest 8200, torn down): (1) guest->host HTTPS over vmbr0 with fingerprint-pin + bearer + self-scoping (200/401/403, wrong-pin TLS fail, no firewall rule needed); (2) config-mount + golden-baked bootstrap unit deploys+runs the controller (docker login/pull/run v0.34.0) with no pct exec. Verdict: GO to 8A spec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.5 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 — Slice 8 Phase A spike: agent↔controller channel + controller deploy plumbing (2026-06-10)
Type
SPIKE (CC-executed on the demo). Doc-only deliverable — no hub/code change, no version bump, no deploy. Probes the two unvalidated foundations of slice 8 before speccing the local API (doc §6) and the provisioning back-half. Findings: documentation/tests/slice8a-channel-deploy-spike-findings.md.
What was proven on demo-felhom
Spike guest 8200 was produced by the real slice-7 bring-up job (felhom-agent v0.9.0,
-mode provision) from the golden archive — a golden, link-up, Docker-29.5.3 guest in 8s, fresh MAC.
Torn down at the end; demo left as found (only pre-existing 9001/9999 remain; golden archive intact).
1. The channel (guest → host HTTPS over vmbr0, fingerprint-pinned) — PASS
A throwaway self-signed HTTPS stub on 192.168.0.162:8443, hit from inside guest 8200:
- correct pin + guest-8200 token → 200; no token → 401; other-guest token → 403 (self-scoping holds); wrong pin → hard TLS failure (curl exit 90 — the pin gates the handshake).
- No firewall rule needed (PVE firewall off; guest and host share the
vmbr0/24, direct route). - Security note: the local-API binds the host LAN IP → reachable by anything on the LAN; auth is the only gate (it held). Both pin forms captured (SPKI + leaf-cert SHA-256) for the 8A choice.
2. The deploy plumbing (no pct exec — config mount + golden-baked unit) — PASS
The F3 principle end-to-end: agent stays host-side, populates a read-only config mount
(/etc/felhom-bootstrap, bind-mount hotplugged live); a golden-baked oneshot reads it →
docker login (token via --password-stdin) → docker pull …/felhom-controller:v0.34.0 →
docker run. The controller came up Up (healthy); an in-guest process read the bootstrap token
from the mount and reached the host /storage → 200. No pct exec used.
Gotchas carried into 8A / the back-half
- Unprivileged-LXC uid mapping — the agent must
chown 100000:100000files it writes into the mount (else the guest reads them asnobody; the secret config is inaccessible). - Registry-cred scope — the bootstrap currently carries the shared
adminpull token; production wants a narrow, read-only, ideally per-guest/short-lived registry token (mount is the right channel). - Controller config contract —
bootstrap.json≠ the controller'scontroller.yaml; the controller boots to setup mode until 8A emits the real config format/path (or the unit translates). - Pin form (SPKI vs leaf-cert SHA-256) and LAN exposure narrowing — 8A/back-half decisions.
Verdict — GO to spec 8A (local-API server + the 7 §6 endpoints) and the provisioning back-half.
Secret handling (held)
Test local-API tokens + the registry pull cred kept in 0600 host files, referenced by location,
never logged/committed; the stub never logged the Authorization header; docker login via
--password-stdin. No real per-guest token or registry cred in git. All scratch shredded on teardown.
No throwaway registry token was minted (the existing gitea-creds admin cred was used by reference).