fix(gateway): persist mitmproxy CA on the host, not a named volume (#450) #454
Reference in New Issue
Block a user
Delete Branch "fix/issue-450-gateway-ca-persistence"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
The shared gateway self-generates a mitmproxy CA that every bottle installs to trust its TLS interception. That CA was persisted on a Docker named volume, which survives
docker rmbut is silently wiped bydocker volume prune/docker system prune --volumesduring routine host maintenance. When that happens, the gateway mints a fresh CA on the next restart and every already-running bottle fails the TLS handshake — even after it re-resolves and reconnects to the moved gateway. This is the fourth re-attachment blocker described in #450, distinct from #443/#445.Change
host_gateway_ca_dir()→bot_bottle_root()/gateway-ca, bind-mounted into the infra/gateway container at mitmproxy's confdir. This mirrors how the shared DB and control-plane token already live under the app-data root. Docker never prunes a path under the root, and it stays directly inspectable + rotatable from the host.rotate_gateway_ca()clears the persisted CA so the next start remints it, andpython -m bot_bottle.orchestrator.rotate_cawires that together with dropping the running gateway container (whose mitmproxy still holds the old CA in memory). Rotation stays an operator action — it doesn't auto-re-provision running bottles, which re-attach to install the new anchor.Maps 1:1 to the issue's proposed solution (persist to host FS → bind-mount → adopt-on-startup → explicit rotation).
Scope
Fixes the Docker infra/gateway path — the "infra container" in the report (
OrchestratorService,DockerGateway). The macOS (container-only volume) and Firecracker (VM-attached ext4 file) backends persist the CA by other means and are unaffected.Tests
rotate_gateway_caunit tests: removes onlymitmproxy-ca*material (leaves the non-CA trust bundle), defaults to the host CA dir, idempotent when empty.test_orchestrator_rotate_ca: the one-shot CLI clears the CA and force-removes both gateway container names; succeeds with no persisted CA./gateway-ca) rather than a named volume.Docs: PRD 0070 gains a "Gateway CA: host-resident, like the DB" subsection capturing the why + rotation.
Closes #450.
🤖 Generated with Claude Code
macOS is now covered by this PR as of
60c9f8a.The Apple "container-only volume" is the named ext4 volume mounted at
/var/lib/bot-bottle; it exists specifically to keep SQLite access within one guest kernel. It did not cover mitmproxy’s CA directory at/home/mitmproxy/.mitmproxy, so recreating the infra container silently generated a new CA.The macOS backend now bind-mounts the host-resident
gateway-cadirectory into mitmproxy’s confdir, matching the Docker fix. The DB remains on its container-only volume, while the CA survives both infra-container recreation andcontainer volume prune. Regression coverage and PRD rationale are included.