Manage SSH Keys and the SSH Agent
Generate ed25519 and RSA SSH keys, manage passphrases with ssh-agent and keychain, forward credentials safely, and harden with FIDO2 hardware tokens.
Before you start
- ▸OpenSSH client installed (openssh-client on Debian/Ubuntu, openssh on Fedora/Arch)
- ▸SSH access to at least one remote host for testing key deployment
- ▸For FIDO2 keys: OpenSSH 8.2 or newer and a FIDO2-compatible hardware token
SSH keys beat passwords on every axis: they are longer, unpredictable, and can be protected by a passphrase without slowing down scripted logins. This guide walks through generating modern keys, wiring up the SSH agent so you type your passphrase only once per session, forwarding credentials safely to jump hosts, and optionally anchoring keys to hardware tokens. The advice here applies to any current Linux distribution.
Choosing a Key Type: ed25519 vs RSA
Two key types dominate practical use today.
- ed25519 — Use this unless you have a specific reason not to. It produces tiny keys (68-character public key), signs and verifies fast, and has no known weaknesses. Requires OpenSSH 6.5+ (standard on any LTS released after 2016).
- RSA — Still the widest-compatibility choice. Use a minimum of 4096 bits. Necessary when connecting to legacy appliances, old cloud APIs, or hardware that predates elliptic-curve support.
Avoid DSA entirely — it is disabled by default in modern OpenSSH. Avoid ECDSA unless a specific platform requires it; ed25519 is strictly preferable for new keys.
Generating a Key Pair
ed25519 (recommended)
ssh-keygen -t ed25519 -C "[email protected]"
The -C flag adds a comment embedded in the public key — useful for identifying keys across many servers. Accept the default path (~/.ssh/id_ed25519) or supply a custom one. Always set a strong passphrase when prompted; the agent will handle re-entering it.
RSA (legacy compatibility)
ssh-keygen -t rsa -b 4096 -C "[email protected]"
File permissions matter
OpenSSH refuses to use keys with loose permissions. Set them once after generation:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
Copying the Public Key to a Remote Host
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote-host
This appends the public key to ~/.ssh/authorized_keys on the remote host with correct permissions. If ssh-copy-id is unavailable, do it manually:
cat ~/.ssh/id_ed25519.pub | ssh user@remote-host \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
The SSH Agent: Type Your Passphrase Once
The SSH agent holds decrypted private keys in memory for the duration of a session. You unlock a key once; the agent handles all subsequent authentications silently.
Starting the agent manually
eval "$(ssh-agent -s)"
Most desktop environments (GNOME, KDE) start an agent automatically at login via systemd user units or a D-Bus service. Check whether one is already running:
echo $SSH_AUTH_SOCK
A non-empty path means an agent is active.
Adding a key to the agent
ssh-add ~/.ssh/id_ed25519
Add -t 3600 to expire the key from the agent after one hour — a sensible limit on shared or laptop systems.
ssh-add -t 3600 ~/.ssh/id_ed25519
List loaded keys
ssh-add -l
Output looks similar to: 256 SHA256:abc123... [email protected] (ED25519) — one line per loaded key. If the output is The agent has no identities, add your key with ssh-add.
Persistent Agent with keychain
keychain is a shell wrapper that re-uses a single long-running agent across logins and shells, so you type your passphrase once per reboot rather than once per terminal session. Install it first:
Debian / Ubuntu
sudo apt install keychain
Fedora / RHEL / Rocky
sudo dnf install keychain
Arch
sudo pacman -S keychain
Add the following to your ~/.bashrc (or ~/.zshrc):
eval "$(keychain --eval --quiet id_ed25519)"
On first shell open after a reboot, keychain prompts for the passphrase. Every subsequent shell sources the existing agent socket — no repeated prompts.
Agent Forwarding: Authenticate Through Jump Hosts
Agent forwarding lets a remote server use your local agent for onward SSH hops, without ever copying your private key off your machine.
Enable forwarding for specific hosts only
Edit ~/.ssh/config:
Host bastion.example.com
ForwardAgent yes
Host *
ForwardAgent no
Never set ForwardAgent yes for Host *. Anyone with root on a host you forward to can hijack your agent socket and authenticate as you to any server that trusts your key.
Per-connection forwarding
ssh -A [email protected]
From inside the bastion you can then ssh user@internal-host and the local agent handles authentication transparently.
ProxyJump: the modern alternative
For simple jump-host scenarios, ProxyJump is cleaner than agent forwarding and does not expose the agent socket on the intermediate host:
ssh -J [email protected] user@internal-host
Or in ~/.ssh/config:
Host internal-host
ProxyJump [email protected]
Prefer ProxyJump over agent forwarding whenever the remote host is your final destination.
Hardware Tokens (FIDO2 / YubiKey)
OpenSSH 8.2+ supports FIDO2 hardware authenticators (YubiKey, SoloKey, etc.). The private key material never leaves the token; the token itself must be physically present for every authentication.
Generate a resident FIDO2 key
ssh-keygen -t ed25519-sk -O resident -C "yubikey@hostname"
-sk means security key. -O resident stores the key handle on the token itself, so you can retrieve the public key later with ssh-keygen -K from any machine. You will be prompted to touch the token during generation.
Non-resident (handle stored locally)
ssh-keygen -t ed25519-sk -C "yubikey@hostname"
This is slightly simpler but requires the ~/.ssh/id_ed25519_sk key handle file to be present on whatever workstation you use.
Copy the public key to remote hosts with ssh-copy-id as usual. Authentication then requires both the key handle and a physical touch of the token — two-factor by design.
Verifying Everything Works
ssh -v user@remote-host 2>&1 | grep -E 'Offering|Accepted|Authentication'
Look for a line like Server accepts key: ... and Authenticated to remote-host. The -v flag also reveals whether the agent was consulted (Offering public key) or whether password fallback occurred.
Troubleshooting
- Permission denied (publickey) — Check
~/.ssh/authorized_keyspermissions on the server (must be 600). Verify the correct public key is present. Runssh-add -lto confirm the key is in the agent. - Agent not running / SSH_AUTH_SOCK empty — Start the agent with
eval "$(ssh-agent -s)"or install keychain for persistence. - sign_and_send_pubkey: signing failed with a hardware token — The token may not be plugged in, or udev rules for FIDO devices are missing. On Debian/Ubuntu install
libpam-u2for ensure thefido2-toolspackage is present. Arch users needlibfido2. - ForwardAgent not working — Confirm the server's
/etc/ssh/sshd_confighasAllowAgentForwarding yes(the default). Also check thatSSH_AUTH_SOCKis set on the remote after connecting. - Too many authentication failures — The client is offering too many keys. Use
-o IdentitiesOnly=yes -i ~/.ssh/specific_keyto force a single key.
Frequently asked questions
- Is ed25519 secure enough to replace my existing 4096-bit RSA key?
- Yes. ed25519 is based on Curve25519 and is considered stronger than RSA-4096 in practice, with faster operations and a much smaller key size. Generate a new ed25519 key and add it to your servers alongside the RSA key, then remove the RSA key once you've verified everything works.
- Why shouldn't I set ForwardAgent yes for all hosts?
- Agent forwarding exposes your agent's Unix socket on the remote host. Any user with root access on that server can use the socket to authenticate as you to any server that trusts your key, for as long as your SSH session is open.
- What is the difference between keychain and the desktop GNOME/KDE keyring?
- Desktop keyrings are started by the display manager and tied to your graphical session; they may not be available in headless or server contexts. keychain is a shell-level tool that works in any environment — graphical, TTY, or remote SSH session — and is the reliable choice for servers and mixed workflows.
- Can I use the same SSH key on multiple machines?
- You can copy the private key file to other machines, but it is generally better security practice to generate a separate key pair per device. That way, revoking a lost laptop's key (by removing it from authorized_keys) does not affect your other machines.
- Do FIDO2 hardware token keys work with all SSH servers?
- The server only sees a standard ed25519 public key and has no special requirements; any server running OpenSSH 6.5+ will accept it. The FIDO2 enforcement (requiring the physical token) happens entirely on the client side.
Related guides
Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.