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:
@@ -0,0 +1,119 @@
|
||||
# =============================================================================
|
||||
# fleet-manager — server-side fleet control plane + admin SPA, plus its private
|
||||
# InfluxDB metrics store. Runs on the MANAGEMENT host (never the boot LAN).
|
||||
#
|
||||
# cp .env.example .env # set RP origin, Influx token, cert/PKI paths
|
||||
# ./server-pki.sh # issue the agent-plane server cert (fleet CA)
|
||||
# ../enrol-broker/admin-pki.sh ../dot1x-bench/pki/broker fleet-manager
|
||||
# docker compose up -d influxdb
|
||||
# docker compose run --rm fleet-manager register-admin <you> # passkey link
|
||||
# docker compose up -d fleet-manager
|
||||
#
|
||||
# See DEPLOY.md for the full bring-up (PKI, Let's Encrypt DNS-01, register-admin).
|
||||
#
|
||||
# Trust model (two planes, see README.md):
|
||||
# - admin : HTTPS + WebAuthn passkey, loopback 127.0.0.1:9500 (front with the
|
||||
# mgmt reverse proxy that terminates the LE cert, or expose directly).
|
||||
# - agent : gRPC + mTLS (fleet CA), on a routable mgmt interface so enrolled
|
||||
# hosts can dial in (FLEET_MGR_AGENT_ADDR).
|
||||
#
|
||||
# fleet-manager uses HOST networking (like enrol-broker): it must reach the
|
||||
# broker's admin plane on 127.0.0.1:9443 and bind the agent listener on a
|
||||
# routable mgmt address. InfluxDB stays on a private bridge and is published
|
||||
# ONLY to loopback (127.0.0.1:8086), so the host-networked manager reaches it
|
||||
# while nothing else on any LAN can.
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
# --- metrics store (private; only the manager reads/writes it) --------------
|
||||
influxdb:
|
||||
image: influxdb:2.7
|
||||
restart: unless-stopped
|
||||
# Publish to loopback only — the host-networked manager reaches it at
|
||||
# 127.0.0.1:8086; it is never on the boot/mgmt LAN.
|
||||
ports:
|
||||
- "127.0.0.1:8086:8086"
|
||||
environment:
|
||||
DOCKER_INFLUXDB_INIT_MODE: setup
|
||||
DOCKER_INFLUXDB_INIT_USERNAME: "${INFLUX_ADMIN_USER:-fleet-admin}"
|
||||
DOCKER_INFLUXDB_INIT_PASSWORD: "${INFLUX_ADMIN_PASSWORD:?set INFLUX_ADMIN_PASSWORD in .env}"
|
||||
DOCKER_INFLUXDB_INIT_ORG: "${FLEET_MGR_INFLUX_ORG:-fleet}"
|
||||
DOCKER_INFLUXDB_INIT_BUCKET: "${FLEET_MGR_INFLUX_BUCKET:-fleet_health}"
|
||||
DOCKER_INFLUXDB_INIT_RETENTION: "${INFLUX_RETENTION:-90d}"
|
||||
# Deterministic operator token so the manager can be handed the SAME value
|
||||
# in FLEET_MGR_INFLUX_TOKEN without a post-setup copy step. Treat as a
|
||||
# secret (it lives in .env, which is gitignored).
|
||||
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: "${FLEET_MGR_INFLUX_TOKEN:?set FLEET_MGR_INFLUX_TOKEN in .env}"
|
||||
volumes:
|
||||
- influx-data:/var/lib/influxdb2
|
||||
- influx-config:/etc/influxdb2
|
||||
networks:
|
||||
- fleet-mgmt
|
||||
healthcheck:
|
||||
test: ["CMD", "influx", "ping"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# --- the control plane + embedded SPA --------------------------------------
|
||||
fleet-manager:
|
||||
build: .
|
||||
image: fleet-manager:local
|
||||
restart: unless-stopped
|
||||
# Host networking: reach the broker on 127.0.0.1:9443 + InfluxDB on
|
||||
# 127.0.0.1:8086, and bind the agent gRPC listener on a routable mgmt addr.
|
||||
network_mode: host
|
||||
depends_on:
|
||||
influxdb:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
# admin plane (HTTPS + passkey). Bind loopback; the mgmt proxy (holding the
|
||||
# LE cert) fronts it, or set the cert paths below + expose directly.
|
||||
FLEET_MGR_ADMIN_ADDR: "${FLEET_MGR_ADMIN_ADDR:-127.0.0.1:9500}"
|
||||
FLEET_MGR_ADMIN_CERT: "${FLEET_MGR_ADMIN_CERT:-/pki/admin/fullchain.pem}"
|
||||
FLEET_MGR_ADMIN_KEY: "${FLEET_MGR_ADMIN_KEY:-/pki/admin/privkey.pem}"
|
||||
FLEET_MGR_ADMIN_INSECURE: "${FLEET_MGR_ADMIN_INSECURE:-false}"
|
||||
# WebAuthn RP — MUST be the UI's real origin (origin-bound passkeys).
|
||||
FLEET_MGR_RP_ID: "${FLEET_MGR_RP_ID:?set FLEET_MGR_RP_ID in .env}"
|
||||
FLEET_MGR_RP_ORIGIN: "${FLEET_MGR_RP_ORIGIN:?set FLEET_MGR_RP_ORIGIN in .env}"
|
||||
FLEET_MGR_RP_NAME: "${FLEET_MGR_RP_NAME:-Fleet Command}"
|
||||
FLEET_MGR_ENROLL_KEY_FILE: "/data/enroll.key"
|
||||
FLEET_MGR_ADMIN_STORE: "/data/admins.json"
|
||||
FLEET_MGR_SESSION_TTL_MIN: "${FLEET_MGR_SESSION_TTL_MIN:-720}"
|
||||
|
||||
# agent plane (gRPC + mTLS, fleet CA). Bind a routable mgmt addr so hosts
|
||||
# can dial in; verify host TPM certs against the fleet root.
|
||||
FLEET_MGR_AGENT_ADDR: "${FLEET_MGR_AGENT_ADDR:-:9600}"
|
||||
FLEET_MGR_AGENT_CERT: "/pki/agent/server.crt"
|
||||
FLEET_MGR_AGENT_KEY: "/pki/agent/server.key"
|
||||
FLEET_MGR_AGENT_CLIENT_CA: "/pki/agent/fleet-ca.crt"
|
||||
|
||||
# authorise pillar — drive the enrol-broker admin plane over mTLS.
|
||||
FLEET_MGR_BROKER_URL: "${FLEET_MGR_BROKER_URL:-https://127.0.0.1:9443}"
|
||||
FLEET_MGR_BROKER_CLIENT_CERT: "/pki/broker/clients/fleet-manager.crt"
|
||||
FLEET_MGR_BROKER_CLIENT_KEY: "/pki/broker/clients/fleet-manager.key"
|
||||
FLEET_MGR_BROKER_CA: "/pki/broker/admin-ca.crt"
|
||||
|
||||
# metrics — the manager is the ONLY reader/writer; token stays server-side.
|
||||
FLEET_MGR_INFLUX_URL: "http://127.0.0.1:8086"
|
||||
FLEET_MGR_INFLUX_TOKEN: "${FLEET_MGR_INFLUX_TOKEN:?set FLEET_MGR_INFLUX_TOKEN in .env}"
|
||||
FLEET_MGR_INFLUX_ORG: "${FLEET_MGR_INFLUX_ORG:-fleet}"
|
||||
FLEET_MGR_INFLUX_BUCKET: "${FLEET_MGR_INFLUX_BUCKET:-fleet_health}"
|
||||
|
||||
FLEET_MGR_INVENTORY: "/data/inventory.json"
|
||||
HOSTNQN_BASE: "${HOSTNQN_BASE:-nqn.2026-06.org.example.fleet:host-}"
|
||||
volumes:
|
||||
# Durable state (inventory + admin passkeys + enrol key). Back this up.
|
||||
- fleet-data:/data
|
||||
# PKI, read-only: admin LE cert, agent-plane fleet-CA server cert, and the
|
||||
# broker admin-client cert. See DEPLOY.md / server-pki.sh for what lands here.
|
||||
- ./pki:/pki:ro
|
||||
|
||||
volumes:
|
||||
influx-data:
|
||||
influx-config:
|
||||
fleet-data:
|
||||
|
||||
networks:
|
||||
fleet-mgmt:
|
||||
driver: bridge
|
||||
Reference in New Issue
Block a user