fleet-manager: checkpoint 7 — deployment (compose, PKI, deploy runbook, design-doc updates)

Complete the deployment story for the server-side control plane:

- docker-compose.yml: private InfluxDB (published to loopback only) + a
  host-networked fleet-manager (reaches the loopback enrol-broker on
  127.0.0.1:9443 and binds a routable gRPC agent listener, like the broker).
- .env.example: RP origin (diskless-server.bitasylum.org), Influx token/DB
  password, cert/PKI paths; the Influx token wires influxdb + manager with
  one value.
- server-pki.sh: issue the agent-plane server cert from the fleet CA (step)
  and stage the fleet root as the client-verify CA.
- DEPLOY.md: end-to-end runbook — three-cert PKI (fleet-CA agent cert, broker
  admin-client cert, Let's Encrypt DNS-01 UI cert), register-admin passkey
  bootstrap, compose up, hardware-free smoke test, backups.
- .dockerignore: keep host node_modules/dist/pki/secrets out of the build
  context so the embedded SPA is the one built in-image.
- .gitignore: never commit .env / issued PKI / data.

Design docs marked as-built: fleet-management-design.md as-built note
(resolved forks — gRPC bidi transport, InfluxDB metrics, SPA graphs, passkey
admin auth, broker fold-in "alongside"); tpm-enrolment-design.md (broker
fold-in + agent transport fork resolved); TODO.md #14 → partly built, with
the on-host agent + per-host boot-version assignment (#6) called out as the
remaining work.
This commit is contained in:
Audiobuzz
2026-07-04 08:44:31 +00:00
parent f62c668ce3
commit 2ef0c1747d
10 changed files with 523 additions and 10 deletions
+32 -1
View File
@@ -1371,7 +1371,36 @@ remains documented here if a minimal/auditable cmdline is ever wanted.
**BENCH-VERIFY:** `chrome://policy` shows `ExtensionInstallBlocklist=["*"]` active;
extensions can't install.
## [ ] 14. (DESIGN) Centralised fleet management plane (health/version/usage/maintenance)
## [~] 14. (PARTLY BUILT) Centralised fleet management plane (health/version/usage/maintenance)
**SERVER-SIDE CONTROL PLANE BUILT 2026-07 — `serving/fleet-manager/`** (Go service
+ embedded Svelte SPA). See the **as-built note** at the top of
[docs/fleet-management-design.md](fleet-management-design.md). What shipped and how
the design forks resolved:
- **Two planes:** admin (HTTPS + **WebAuthn/passkey**, YubiKey; server-side session
+ CSRF; `register-admin` CLI bootstrap; UI cert via **Let's Encrypt DNS-01**,
hot-reloaded) and agent (**bespoke gRPC bidi/mTLS**, fleet CA, reused TPM cert —
health/metrics up, desired-state down; no inbound host port).
- **Metrics → InfluxDB** (manager is the only reader/writer; host holds no Influx
credential; identity-tagged writes; Flux reads behind a field whitelist + hex-
serial guard). Graphs render **in the SPA** (bespoke SVG), not Grafana. This
replaces the earlier Wazuh-Phase-1 / OTLP-Phase-2 sketch for *this* plane;
Wazuh stays the audit/SIEM path.
- **Authorise pillar:** the enrol-broker (#11) folded in "alongside" — manager
drives its admin plane over mTLS and **births the inventory record** on approve.
- **Deployment:** `Dockerfile` + `docker-compose.yml` (private InfluxDB +
host-networked manager) + `server-pki.sh` + `DEPLOY.md`.
- **STILL TO BUILD:** (a) the **on-host agent** — the gRPC report/reconcile client
that pairs with `fleet-hostapi` (feeds this plane; nothing on the host talks to
the manager yet); (b) **per-host boot-version assignment** — `target_version` is
stored + pushed but does not change what a host *boots*; that needs dnsmasq
cohort steering + multi-version UKI serving (**#6**). Kiosk URL / reboot / drain
reconcile via the agent once (a) lands. Version pin is labelled "recorded intent"
in the Lifecycle UI.
Depends on the step-ca fleet CA (#8) for the mTLS identity.
<details><summary>Original design capture (2026-06-28) — retained for reference</summary>
**DESIGN CAPTURED 2026-06-28 — [docs/fleet-management-design.md](fleet-management-design.md).**
Server-authoritative, pull-based, TPM-identified management plane reusing existing
@@ -1388,6 +1417,8 @@ manifest + SPDK flow. Build-time decisions (telemetry encoding, metrics/desired-
state store, per-host vs cohort, osquery/FleetDM eval) listed in the design note.
Depends on the step-ca fleet CA (#8) for the mTLS identity.
</details>
## [ ] 15. Scope the root overlay → per-subtree tmpfs/overlay (un-shadowable `/usr` + STIG mount options)
**DESIGN CAPTURED 2026-07-02.** Today the whole root is one `systemd.volatile=overlay`