While working with Git, SSH, and VS Code, Ubuntu may start asking for the private SSH key passphrase repeatedly. This can happen even when the key is already loaded into an agent.
Possible causes include a short passphrase cache lifetime, an incorrect GPG Agent binding to the current terminal, or multiple SSH agents being present in the system.
In this case, the problem was related to GPG Agent: the key was loaded, but the agent periodically lost the ability to perform signing operations without prompting again.
First Check Which SSH Agent Is Active
echo "$SSH_AUTH_SOCK" ssh-add -l ps -ef | grep -E '[s]sh-agent|[g]cr-ssh-agent'In this case, GPG Agent was used:
/run/user/1000/gnupg/S.gpg-agent.ssh
The ED25519 SSH key was loaded, but the system still periodically asked for its passphrase.
GCR SSH Agent was running at the same time. Having two agents does not automatically mean there is a conflict, but it is important to know which one the terminal, Git, and the editor are actually using.
Check the Passphrase Cache Lifetime
if [ -f ~/.gnupg/gpg-agent.conf ]; then grep -E 'cache-ttl|ssh-support|external-cache|pinentry' \ ~/.gnupg/gpg-agent.conf || trueelse echo "No custom GPG agent config"fi gpgconf --list-options gpg-agent | grep -E '^(default-cache-ttl-ssh|max-cache-ttl-ssh):'Typical default values for the GPG Agent SSH cache are:
default-cache-ttl-ssh- 1800 seconds, or 30 minutes;max-cache-ttl-ssh- 7200 seconds, or 2 hours.
Even when the key is used regularly, the maximum cache lifetime still limits how long the agent may keep the passphrase unlocked.
Increase the Cache Lifetime
mkdir -p -m 700 ~/.gnupg cat > ~/.gnupg/gpg-agent.conf <<'EOF'default-cache-ttl-ssh 28800max-cache-ttl-ssh 43200EOF chmod 600 ~/.gnupg/gpg-agent.conf gpgconf --reload gpg-agentThis configuration does not modify the private SSH key and does not remove its passphrase.
It only extends how long GPG Agent can remember a passphrase that has already been entered.
There is a trade-off: a longer cache also means the unlocked key remains available for a longer period in the current session.
Test Whether the Agent Can Perform SSH Signing
ssh-add -T <(ssh-add -L)ssh-add -T <(ssh-add -L)After reloading the configuration, the following error appeared in this case:
Agent signature failed for /dev/fd/63: agent refused operation
This meant that the key was visible in the agent, but the agent itself refused to perform the signing operation.
Update GPG Agent Binding to the Current Terminal
export GPG_TTY="$(tty)" gpg-connect-agent updatestartuptty /byeOne possible reason for agent refused operation is an incorrect GPG Agent binding to the terminal currently used by the user.
After updating the binding, repeat the key and signature checks.
echo "===== SSH KEYS ====="ssh-add -l echoecho "===== SIGNATURE TEST 1 ====="ssh-add -T <(ssh-add -L) echoecho "===== SIGNATURE TEST 2 ====="ssh-add -T <(ssh-add -L)After this change, both signing operations completed without errors.
This confirmed that the agent could use the SSH key again. However, this check alone does not prove that repeated passphrase prompts are permanently gone.
Automatically Update the Binding for New Bash Terminals
if ! grep -qF '# GPG agent terminal setup' ~/.bashrc; then cat >> ~/.bashrc <<'EOF' # GPG agent terminal setupif [[ $- == *i* ]] && [[ -t 0 ]]; then export GPG_TTY="$(tty)" gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1 || truefiEOFfi source ~/.bashrcChecking for the comment before appending the block prevents the same configuration from being written to ~/.bashrc multiple times.
After that, every new interactive Bash shell updates the GPG Agent binding to the current terminal automatically.
Final Verification in a New Terminal
echo "===== SSH AGENT ====="echo "$SSH_AUTH_SOCK" echoecho "===== SSH SIGNATURE ====="ssh-add -T <(ssh-add -L)In this case, SSH_AUTH_SOCK again pointed to /run/user/1000/gnupg/S.gpg-agent.ssh, and the signing test completed without an error message.
For ssh-add -T, no error output means the signing test succeeded.
If the Problem Remains Only in VS Code
If a normal terminal works correctly but VS Code still asks for the passphrase, that is a separate signal.
In that case, inspect which SSH_AUTH_SOCK was inherited by the VS Code process itself and whether the integrated terminal sees the same environment variables.
After fixing GPG Agent, do not immediately replace the key. First separate an agent problem from an environment problem in the graphical application.
What Was Fixed
During troubleshooting, we:
- checked the active SSH Agent and loaded keys;
- identified the current passphrase cache limits;
- extended the cache lifetime to 8-12 hours;
- found the
agent refused operationerror; - updated the GPG Agent binding to the current terminal;
- added automatic initialization to
~/.bashrc; - successfully verified SSH signing in a new terminal.
A key can be loaded into an agent without the agent being correctly bound to the current terminal or ready to perform signing.



