From f089adf26185979a9b28cc975087e102559b1a28 Mon Sep 17 00:00:00 2001 From: Keith Jackson Date: Sun, 16 Aug 2026 22:31:51 -0500 Subject: [PATCH] devcontainer: set KUBECONFIG + persist SOPS age key to host Two dev.sh gaps surfaced while running bootstrap/sops/install-age-key.sh: - kubectl defaulted to localhost:8080 (connection refused) because KUBECONFIG was never set in the toolbox. Set KUBECONFIG=/work/infra/ansible/.cache/dev.kubeconfig (override via DEV_KUBECONFIG); --network host already reaches 10.73.0.11:6443. - age-keygen.sh writes the PRIVATE key to ~/.config/sops/age/keys.txt, but that path was not mounted in the --rm container, so the key was lost on exit. Mount ${HOME}/.config/sops -> /root/.config/sops (created first) so the key persists on the host and SOPS_AGE_KEY_FILE resolves to it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .sops.yaml | 4 ++-- infra/devcontainer/dev.sh | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.sops.yaml b/.sops.yaml index 359bbd8..ad8295f 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -28,9 +28,9 @@ creation_rules: encrypted_regex: "^(data|stringData)$" # >>> REPLACE-ME <<< paste the age PUBLIC recipient printed by age-keygen.sh. # Example shape (NOT a real key): age1qy...placeholder...0abcd - age: "REPLACE-ME-AGE-PUBLIC-RECIPIENT" + age: "age1u70g00m38pt4zte00n4fsqfyj3rf8725xn4w7e6lx80evt4rcalsdnprp8" - path_regex: (^|/)secrets/.*\.ya?ml$ encrypted_regex: "^(data|stringData)$" # >>> REPLACE-ME <<< same age PUBLIC recipient as above. - age: "REPLACE-ME-AGE-PUBLIC-RECIPIENT" + age: "age1u70g00m38pt4zte00n4fsqfyj3rf8725xn4w7e6lx80evt4rcalsdnprp8" diff --git a/infra/devcontainer/dev.sh b/infra/devcontainer/dev.sh index edd424a..b63c7ac 100755 --- a/infra/devcontainer/dev.sh +++ b/infra/devcontainer/dev.sh @@ -30,13 +30,21 @@ build() { } run() { + # Persist the SOPS age keyring on the HOST so the age PRIVATE key generated by + # bootstrap/sops/age-keygen.sh survives this --rm container (otherwise it lives only + # in the ephemeral container fs and is lost on exit — you'd be locked out of every + # SOPS-encrypted secret). SOPS_AGE_KEY_FILE defaults to ~/.config/sops/age/keys.txt, + # which is this mount. Create it first so the bind source exists. + mkdir -p "${HOME}/.config/sops/age" "$ENGINE" run --rm -it \ --network host \ --security-opt label=disable \ -v /run/libvirt:/run/libvirt \ -v "${REPO_ROOT}:/work" -w /work \ -v "${HOME}/.ssh:/root/.ssh:ro" \ + -v "${HOME}/.config/sops:/root/.config/sops" \ -e LIBVIRT_DEFAULT_URI=qemu:///system \ + -e KUBECONFIG="${DEV_KUBECONFIG:-/work/infra/ansible/.cache/dev.kubeconfig}" \ "$IMAGE" "$@" }