gpg-agent: Passphrase Caching and Loopback
gpg-agent is the GnuPG 2.x daemon that holds secret keys and passphrases on behalf of gpg.
In GnuPG 2.x every secret-key operation goes through gpg-agent. Understanding it explains why CI needs loopback mode and how to reset state between jobs.
What it does
gpg-agent manages private keys and caches passphrases so gpg does not re-prompt. It launches pinentry to collect passphrases. gpg starts it automatically under the active GNUPGHOME. Its behavior is configured in gpg-agent.conf within that directory.
Common usage
# allow loopback pinentry, then reload the agent
mkdir -p "$GNUPGHOME" && chmod 700 "$GNUPGHOME"
echo "allow-loopback-pinentry" >> "$GNUPGHOME/gpg-agent.conf"
gpgconf --kill gpg-agent # restart so the config takes effect
# stop the agent at job end
gpgconf --kill gpg-agentOptions
| Setting / command | What it does |
|---|---|
| allow-loopback-pinentry | gpg-agent.conf line permitting --pinentry-mode loopback |
| default-cache-ttl <s> | How long a cached passphrase stays valid |
| gpgconf --kill gpg-agent | Stop the running agent (it restarts on next use) |
| gpgconf --launch gpg-agent | Start the agent explicitly |
| gpg-connect-agent reloadagent /bye | Reload agent config without killing it |
In CI
GnuPG 2.x routes everything through the agent, which is why bare gpg --passphrase does not work without --pinentry-mode loopback and an agent that permits it. After writing gpg-agent.conf, kill the agent so it reloads. Use a fresh ephemeral GNUPGHOME per job so a stale socket or cached passphrase never leaks across runs.
Common errors in CI
"gpg: setting pinentry mode 'loopback' failed: Not supported" means allow-loopback-pinentry is missing or the agent has not reloaded; add it and run gpgconf --kill gpg-agent. "gpg-agent: a gpg-agent is already running" with a stale socket happens when reusing GNUPGHOME across jobs; use a fresh directory. "can't connect to the agent" points at a wrong or unwritable GNUPGHOME.