v0.43.0: canonical systemd unit + publish agent binary + golden to Gitea (BUNDLE slice)

- configs/felhom-agent.service: canonical non-root unit (User=felhom-agent, sudo model);
  deliberately NO NoNewPrivileges (breaks sudo) and NO mount-namespacing hardening (breaks
  the intermediary-mount drive propagation into guests) — documented inline.
- scripts/publish-agent.sh: build (optional) + PUT binary to Gitea generic + sha256 +
  GET round-trip. Pinned version, idempotent (delete-then-PUT).
- configs/build-golden.sh: after vzdump, compute sha256 + PUT golden.tar.zst to Gitea
  generic (version = baked controller version). Opt-in; local auto-discovery stays fallback.
- cmd/felhom-agent/main.go: version 0.42.0 -> 0.43.0.
- README: process model now canonical (non-root + publish/install).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 08:38:01 +02:00
parent aaa276a7b9
commit 29aeaa6bb4
6 changed files with 243 additions and 5 deletions
+20 -4
View File
@@ -205,11 +205,27 @@ so cleanly if the token/endpoint isn't configured.
`--selftest=task --vmid N` (explicitly gated) exercises `WaitTask` on a **reversible** op
(snapshot → rollback → delete-snapshot) against guest `N`. Default `--selftest` never mutates.
## Process model (proposed, not finalized — see 03 §3/§12)
## Process model
Native Go binary, systemd service, **non-root** service user holding the scoped token, with a
**narrow sudoers allowlist** for the three fenced ops. `privileged.mode: "sudo"` matches this;
`"direct"` is for dev/CI where the agent is already root.
Native Go binary, systemd service, **non-root** `felhom-agent` service user holding the scoped token,
with a **narrow sudoers allowlist** for the fenced host-root ops. `privileged.mode: "sudo"` matches
this; `"direct"` is for dev/CI where the agent is already root.
The canonical artifacts (BUNDLE slice):
- **`configs/felhom-agent.service`** — the canonical unit (`User=felhom-agent`,
`ExecStart=/usr/local/bin/felhom-agent --config /etc/felhom-agent/agent.json`). It deliberately sets
**no** `NoNewPrivileges` and **no** mount-namespacing hardening (`ProtectHome`/`PrivateTmp`/…): the
first would block the `sudo` the agent needs, the second would put the agent in a private mount
namespace so its `mount --bind` drive enrollments wouldn't propagate into the running guest. The
security boundary is the sudoers allowlist, not systemd sandboxing.
- **`configs/felhom-agent.sudoers`** → `/etc/sudoers.d/felhom-agent` (0440, `visudo -cf`-validated).
- **`scripts/publish-agent.sh`** publishes the binary to Gitea as a generic package
(`/api/packages/admin/generic/felhom-agent/<ver>/felhom-agent`), printing the sha256 the operator
records in the hub artifact manifest.
**Install is automated.** The host-bootstrap script (`felhom.eu/scripts/felhom-host-install.sh`) fetches
the binary from Gitea, verifies its sha256 against the hub-vouched manifest, then installs the user +
binary + sudoers + unit + config — no manual agent install step.
## Test