0% прочитано

Ubuntu Keeps Asking for an SSH Key Passphrase: Configuring GPG Agent

When working with Git, SSH, and VS Code, Ubuntu may repeatedly ask for the private SSH key passphrase. This article shows how to inspect the active agent, extend passphrase caching, update the GPG Agent terminal binding, and verify signing.

1 листопада 2026 р. 8 хв читанняDevOps

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

Check the active agent and loaded keys
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

Check GPG Agent cache settings
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

8 hours after last use, 12 hours maximum
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-agent

This 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

Two consecutive signing checks
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

Update the binding to the current terminal
export GPG_TTY="$(tty)" gpg-connect-agent updatestartuptty /bye

One 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.

Repeat the test after updating the binding
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

Initialize GPG Agent in every new interactive Bash shell
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 ~/.bashrc

Checking 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

Verify after opening 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:

  1. checked the active SSH Agent and loaded keys;
  2. identified the current passphrase cache limits;
  3. extended the cache lifetime to 8-12 hours;
  4. found the agent refused operation error;
  5. updated the GPG Agent binding to the current terminal;
  6. added automatic initialization to ~/.bashrc;
  7. successfully verified SSH signing in a new terminal.
This problem does not require immediately removing the passphrase from the private SSH key or generating a new key. First inspect the agent, cache settings, and terminal binding.

A key can be loaded into an agent without the agent being correctly bound to the current terminal or ready to perform signing.