Load SSH keys safely with ssh-add and verify the agent
You will load an existing private SSH key into the authentication agent, confirm that the agent has it, and set a lifetime when the key should not remain available indefinitely. Allow about five minutes if the key file already exists. This guide covers the OpenSSH client installed here, version 1:9.6p1-3ubuntu13.19 from the openssh-client package.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Check the command and the agent socket
- 2. Start a temporary agent when none is available
- 3. Confirm the private key file and its permissions
- 4. Add the key with a bounded lifetime
- 5. Verify the loaded identity
- 6. Check key usability without making an SSH connection
- 7. Remove one key or clear the agent deliberately
- 8. Reduce forwarding risk for a multi-hop connection
Prerequisites: a private key such as ~/.ssh/id_ed25519, its passphrase if it has one, and a running ssh-agent. The examples run as your normal user. They do not need sudo, and using sudo ssh-add would usually load a key into root's separate agent context, not yours.
1. Check the command and the agent socket
ssh-add communicates with the agent through the Unix socket named by SSH_AUTH_SOCK. Check both pieces before troubleshooting a key file:
$ command -v ssh-add
/usr/bin/ssh-add
$ dpkg-query -W -f='${Package} ${Version}\n' openssh-client
openssh-client 1:9.6p1-3ubuntu13.19
$ printf 'SSH_AUTH_SOCK=%s\n' "${SSH_AUTH_SOCK:-unset}"
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket
Your socket path and package version may differ. An unset variable means there is no agent endpoint for ssh-add to use. A path can also be present while the agent has stopped, so the next check matters.
2. Start a temporary agent when none is available
If your desktop session or login shell already provides an agent, skip this step. Otherwise start one in the current shell:
$ eval "$(ssh-agent -s)"
Agent pid 12345
The PID is an example and will vary. The command exports SSH_AUTH_SOCK and SSH_AGENT_PID into this shell. Confirm contact without changing key state:
$ ssh-add -l
The agent has no identities.
If the output is Could not open a connection to your authentication agent, inspect SSH_AUTH_SOCK and the shell in which you ran ssh-agent. Do not copy a socket path from another login session. When you deliberately started a temporary agent, stop it after this work with eval "$(ssh-agent -k)"; that removes the agent process and its loaded identities.
3. Confirm the private key file and its permissions
Use a real path that you control. The command below only inspects the file:
$ KEY="$HOME/.ssh/id_ed25519"
$ test -f "$KEY" && test -r "$KEY" && printf 'readable: %s\n' "$KEY"
readable: /home/alice/.ssh/id_ed25519
$ stat -c '%A %n' "$KEY"
-rw------- /home/alice/.ssh/id_ed25519
Replace the path if your key has another name. The installed manual says identity files are ignored when they are readable by someone other than their owner. If the permissions are too broad, correct them only after checking that the file is the intended private key:
$ chmod 600 "$KEY"
$ stat -c '%A %n' "$KEY"
-rw------- /home/alice/.ssh/id_ed25519
This changes file metadata, not the key material. Do not print the private key or paste it into a terminal transcript.
4. Add the key with a bounded lifetime
Load the key for one hour with -t. ssh-add reads a passphrase from the terminal when required, so type it at the prompt and do not put it in a shell command:
$ ssh-add -t 1h "$KEY"
Enter passphrase for /home/alice/.ssh/id_ed25519:
Identity added: /home/alice/.ssh/id_ed25519 (alice@example)
Lifetime set to 3600 seconds
The comment in parentheses comes from the public key and is not proof of the account or host to which the key grants access. A lifetime limits how long the agent will offer the identity; it does not alter the private key file. Omit -t only when your agent's normal lifetime policy is understood.
If you need a key to require an approval for each use, add it with confirmation enabled:
$ ssh-add -c -t 1h "$KEY"
Enter passphrase for /home/alice/.ssh/id_ed25519:
Identity added: /home/alice/.ssh/id_ed25519 (alice@example)
Lifetime set to 3600 seconds
Confirmation relies on ssh-askpass. Test that workflow before depending on it for an unattended job.
5. Verify the loaded identity
List fingerprints rather than exposing private-key contents:
$ ssh-add -l
256 SHA256:REPLACE_WITH_YOUR_FINGERPRINT alice@example (ED25519)
Your fingerprint, comment and key type will differ. The default fingerprint display uses SHA-256. If you need to compare with an older record that uses MD5, request it explicitly:
$ ssh-add -l -E md5
256 MD5:REPLACE_WITH_YOUR_FINGERPRINT alice@example (ED25519)
To see public-key parameters rather than fingerprints, use ssh-add -L. Both commands query the agent and do not reveal the private key.
6. Check key usability without making an SSH connection
If you have the matching public key file, -T asks the agent to perform a sign and verify operation. This checks that the private key corresponding to the public key is usable:
$ ssh-add -T "$KEY.pub"
$ printf 'ssh-add test status: %s\n' "$?"
ssh-add test status: 0
No output is normal on success. A non-zero result can mean the public key does not match an identity in the agent, the key has expired from the agent, the agent is locked, or the key cannot perform the requested operation. This test does not prove that a remote server accepts the key.
7. Remove one key or clear the agent deliberately
When the key is no longer needed, remove it by naming its public key. This changes the agent state but leaves the key files alone:
$ ssh-add -d "$KEY.pub"
Identity removed: /home/alice/.ssh/id_ed25519
Verify removal with ssh-add -l. If the agent contains several keys, do not use ssh-add -D casually: it deletes every identity from that agent. This cannot be undone by ssh-add; reload each required key with its passphrase.
Locking is different from removal. ssh-add -x locks the agent with a password and ssh-add -X unlocks it. Use those options only when you understand how your agent handles locking and recovery.
8. Reduce forwarding risk for a multi-hop connection
By default, keys added by ssh-add are not destination constrained. If the key will be used through agent forwarding, a constraint such as the following restricts it to a named destination:
$ ssh-add -h '[alice@]build.example.net' -t 1h "$KEY"
Enter passphrase for /home/alice/.ssh/id_ed25519:
Identity added: /home/alice/.ssh/id_ed25519 (alice@example)
Lifetime set to 3600 seconds
Use the actual destination hostname and user syntax for your route. The host must be found through a known-hosts file, and a forwarded multi-hop path must satisfy every hop's constraint. Destination constraints were added in OpenSSH 8.9, and support is required in the remote SSH client and server for forwarded use. They limit permitted destinations, but do not make a compromised remote SSH_AUTH_SOCK harmless. Avoid agent forwarding to hosts you do not trust.
Done means
ssh-addandopenssh-clientwere checked, and the agent socket is reachable.- The intended private key was readable only by its owner.
- The key was added without putting its passphrase in shell history.
ssh-add -lshows the expected fingerprint, with an optional lifetime.ssh-add -Treturned status 0 when a matching public key was available.- Unneeded identities were removed, and agent forwarding is limited to trusted hosts.