fix(gateway): persist git-gate state across gateway restarts
Per-bottle git-gate state (bare repos under /git/<id>, deploy creds under /git-gate/creds/<id>) was provisioned once at bottle launch and lived only in the gateway's ephemeral storage. A gateway rebuild/restart wiped it and nothing re-provisioned already-running bottles, so their agents 404'd on fetch/push. Same class of bug as the CA (#510); the orchestrator restores only egress tokens, not git-gate declarations. Persist the state on both backends, mirroring the CA-persistence approach: - firecracker: attach a second persistent data drive (/dev/vdc) to the gateway VM and bind-mount its git/ + creds/ subdirs onto /git and /git-gate/creds in the gateway guest init, before the data plane starts. Generalize the VM config to a stable-ordered data_drives tuple (CA=vdb, git=vdc; orchestrator registry stays vdb). - docker: bind-mount host dirs (host_gateway_git_dir / creds_dir, under the never-pruned app-data root) onto /git and /git-gate/creds, with BOT_BOTTLE_DOCKER_GIT_MOUNT / _CREDS_MOUNT env overrides so CI isolates them to per-run volumes it cleans up. Teardown already rm -rf's /git/<id> + creds, so the persistent store self-cleans over the normal lifecycle. Closes #512 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,15 @@ ORCHESTRATOR_AUTH_JWT_ENV = "BOT_BOTTLE_ORCHESTRATOR_AUTH_JWT"
|
||||
# the shared gateway's TLS interception, so it must not rotate on restart. See
|
||||
# host_gateway_ca_dir() for why this is a host bind-mount, not a named volume.
|
||||
GATEWAY_CA_DIRNAME = "gateway-ca"
|
||||
# The host directories holding the gateway's persistent git-gate state — the
|
||||
# per-bottle bare repos (`gateway-git`) and deploy creds (`gateway-creds`).
|
||||
# Bind-mounted into the gateway container at /git and /git-gate/creds so they
|
||||
# survive container recreation; without it a gateway restart drops every
|
||||
# already-running bottle's git-gate state and its agent 404s on fetch/push
|
||||
# (issue #512). Host bind-mounts (not named volumes) for the same reason as the
|
||||
# CA dir — see host_gateway_ca_dir().
|
||||
GATEWAY_GIT_DIRNAME = "gateway-git"
|
||||
GATEWAY_CREDS_DIRNAME = "gateway-creds"
|
||||
|
||||
|
||||
def bot_bottle_root() -> Path:
|
||||
@@ -97,6 +106,27 @@ def host_gateway_ca_dir() -> Path:
|
||||
return ca_dir
|
||||
|
||||
|
||||
def host_gateway_git_dir() -> Path:
|
||||
"""The directory holding the gateway's persistent per-bottle bare repos,
|
||||
created if missing. Bind-mounted into the gateway container at /git so the
|
||||
repos survive container recreation (issue #512). A host bind-mount under the
|
||||
app-data root, never pruned — same rationale as host_gateway_ca_dir()."""
|
||||
git_dir = bot_bottle_root() / GATEWAY_GIT_DIRNAME
|
||||
git_dir.mkdir(parents=True, exist_ok=True)
|
||||
return git_dir
|
||||
|
||||
|
||||
def host_gateway_creds_dir() -> Path:
|
||||
"""The directory holding the gateway's persistent per-bottle git-gate deploy
|
||||
creds, created if missing. Bind-mounted into the gateway container at
|
||||
/git-gate/creds so the creds survive container recreation (issue #512). A
|
||||
host bind-mount under the app-data root — same rationale as
|
||||
host_gateway_ca_dir()."""
|
||||
creds_dir = bot_bottle_root() / GATEWAY_CREDS_DIRNAME
|
||||
creds_dir.mkdir(parents=True, exist_ok=True)
|
||||
return creds_dir
|
||||
|
||||
|
||||
def host_signing_key(filename: str) -> str:
|
||||
"""A per-host signing key at `<root>/<filename>`, minted (256-bit, url-safe)
|
||||
and persisted 0600 on first use, then reused.
|
||||
@@ -143,10 +173,14 @@ __all__ = [
|
||||
"ORCHESTRATOR_TOKEN_ENV",
|
||||
"ORCHESTRATOR_AUTH_JWT_ENV",
|
||||
"GATEWAY_CA_DIRNAME",
|
||||
"GATEWAY_GIT_DIRNAME",
|
||||
"GATEWAY_CREDS_DIRNAME",
|
||||
"bot_bottle_root",
|
||||
"host_db_path",
|
||||
"host_db_dir",
|
||||
"host_gateway_ca_dir",
|
||||
"host_gateway_git_dir",
|
||||
"host_gateway_creds_dir",
|
||||
"host_signing_key",
|
||||
"host_orchestrator_token",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user