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
+19 -5
View File
@@ -146,6 +146,18 @@ pinned for mTLS — one trust anchor across 802.1X, NVMe, and management.
everything else on. Build the broker standalone first (fastest path to the state
machine), but design it to fold into the mgmt service with no rewrite — same Go
style, same step-ca anchor, same data model.
- **AS-BUILT (2026-07): folded in "alongside", not merged.** The
`serving/fleet-manager/` control plane drives the standalone broker's admin
plane over mTLS (broker admin CA) rather than absorbing its code: the broker
stays the enrolment **state machine + step-ca signer**, and gained an
`Accept: application/json` approve response so the manager gets the decided
enrolment back and **births the inventory record**, recording the human
(passkey-authenticated) admin as approver. `verify-serving.sh` / browser
callers are unchanged (still get the 204/redirect). The public
`/enrol/request|status` edge is untouched. This keeps the one unauth,
stdlib-only, reproducible pre-auth parser isolated while giving the manager
the authenticated authorise pillar — same trust anchor, same data model, no
rewrite. See `serving/fleet-manager/README.md` (Authorise pillar).
- **host-api is not in the enrolment path** (it is loopback/post-boot; the host has
no cert during enrolment). The tie is downstream: the fleet-manager **agent** (the
push sibling of `fleet-hostapi`) authenticates with the *enrolled* cert over mTLS,
@@ -200,11 +212,13 @@ fleet-manager agent) — one language, one build/posture story. Transport is spl
- **Steady-state agent ↔ manager (telemetry + reconciliation) → gRPC over mTLS,
host-dialed.** Streaming fits here, and it stays compatible with "no inbound port on
hosts" because the **host dials out** and holds one long-lived mTLS stream (health
up / desired-state down). OPEN FORK (a fleet-manager build decision, not enrolment):
bespoke gRPC vs reuse **OTLP-gRPC for metrics + Wazuh for events** + a thin gRPC
control stream — the latter gets VictoriaMetrics/Grafana/Wazuh for free. `Connect`
(connectrpc.com) is an option if one protobuf IDL serving gRPC + JSON + browser is
wanted across the authenticated surface.
up / desired-state down). ~~OPEN FORK~~ **RESOLVED (2026-07):** a **bespoke gRPC
bidi stream** (`serving/fleet-manager/proto/fleet_agent.proto` —
`FleetAgent.Session`, health/metrics up + desired-state down), over the same
reused TPM cert (fleet CA). Metrics land in **InfluxDB** via the manager (host
holds no Influx credential), not OTLP→VictoriaMetrics; events stay on the Wazuh
path. One stream, no polling, no inbound host port. (The on-host agent — the
gRPC report/reconcile client that pairs with `fleet-hostapi` — is still to build.)
- **host-api stays HTTP/JSON — locked**, because its consumer is the Chromium kiosk
(a browser, which cannot speak native gRPC).