From b40dfdd1f3d6e6a9c28f32dd639685740c795625 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Wed, 8 Jul 2026 12:55:30 +0000 Subject: [PATCH] chore: enhance devcontainer setup with GPG keyring support and improved signing process --- .devcontainer/Dockerfile | 4 +++- .devcontainer/README.md | 24 ++++++++++++++---------- .devcontainer/devcontainer.json | 3 ++- .devcontainer/post-start.sh | 3 ++- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b5b7d4c7f5..b0b421d9e0 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -19,7 +19,9 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* \ && corepack enable \ && mkdir -p ${PNPM_HOME} /home/node/.pnpm-store /commandhistory \ + && mkdir -p /home/node/.gnupg \ && touch /commandhistory/.bash_history \ - && chown -R node:node /home/node/.local /home/node/.pnpm-store /commandhistory \ + && chmod 700 /home/node/.gnupg \ + && chown -R node:node /home/node/.local /home/node/.pnpm-store /commandhistory /home/node/.gnupg \ && echo "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" >> /home/node/.bashrc USER node diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 36ab112ab2..e9105b3e49 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -71,11 +71,12 @@ private keys never enter the container, only the agent socket is forwarded: installed). This enables the actual signing operation via the host agent. - Your host **SSH agent** is forwarded, so `git push` over SSH uses your host keys. -**Important**: VS Code forwards the host agent socket but does **not** automatically -copy your host GPG public keyring into the container. GPG requires both a public key -entry in the container's local keyring (to select the key) and the forwarded agent -(to perform the signing). Without the public key, `gpg --clearsign` fails with -`No secret key` even though the host agent connection is active. +By default this devcontainer bind-mounts the host public keyring file +(`${localEnv:HOME}/.gnupg/pubring.kbx`) into the container at +`/home/node/.gnupg/pubring.kbx` (read-only), so you do not need to export/import +the public key on each rebuild. + +The host `gpg-agent` forwarding is still required for actual signing operations. ### One-time host setup @@ -86,7 +87,9 @@ entry in the container's local keyring (to select the key) and the forwarded age git config --global commit.gpgsign true ``` -2. Export your public key so the container can import it: +2. Optional fallback: export your public key so the container can import it + when the host pubring mount is unavailable (for example host setups without + `~/.gnupg/pubring.kbx`): ```bash # on the HOST, from repo root (auto-uses git user.signingkey) @@ -106,14 +109,15 @@ entry in the container's local keyring (to select the key) and the forwarded age .\.devcontainer\export-signing-key.ps1 ``` -3. Rebuild the container. The `postStartCommand` auto-imports `.git/signing.pub` - on every container start, so signing survives restarts and rebuilds without - re-running the export script. +3. Rebuild the container. If the host pubring is mounted, signing should work + without export/import. If it is not mounted, the `postStartCommand` imports + `.git/signing.pub` when available. The helper auto-selects `gpg2`/`gpg` based on where your key is visible, which avoids host setups where the two binaries use different keyrings. -If you rotate keys, run the export helper again on the host before the next rebuild. +If you rotate keys, rebuild so the mounted pubring reflects host changes. If you +use the fallback export/import path, run the export helper again before rebuild. Expected behavior after rebuild: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1fae7a9d74..7341549d9b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -54,7 +54,8 @@ "mounts": [ "source=workspace-pnpm-store,target=/home/node/.pnpm-store,type=volume", - "source=workspace-bashhistory,target=/commandhistory,type=volume" + "source=workspace-bashhistory,target=/commandhistory,type=volume", + "source=${localEnv:HOME}/.gnupg/pubring.kbx,target=/home/node/.gnupg/pubring.kbx,type=bind,consistency=cached,readonly" ], "postCreateCommand": ".devcontainer/post-create.sh", diff --git a/.devcontainer/post-start.sh b/.devcontainer/post-start.sh index 3722114759..6a538bffc8 100755 --- a/.devcontainer/post-start.sh +++ b/.devcontainer/post-start.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -if [ -f .git/signing.pub ]; then +# If pubring.kbx is bind-mounted read-only from host, skip import fallback. +if [ -f .git/signing.pub ] && [[ ! -f "${HOME}/.gnupg/pubring.kbx" || -w "${HOME}/.gnupg/pubring.kbx" ]]; then gpg --import .git/signing.pub fi