$linuxjunkies
>

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.

BeginnerUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

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

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_keys permissions on the server (must be 600). Verify the correct public key is present. Run ssh-add -l to 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-u2f or ensure the fido2-tools package is present. Arch users need libfido2.
  • ForwardAgent not working — Confirm the server's /etc/ssh/sshd_config has AllowAgentForwarding yes (the default). Also check that SSH_AUTH_SOCK is set on the remote after connecting.
  • Too many authentication failures — The client is offering too many keys. Use -o IdentitiesOnly=yes -i ~/.ssh/specific_key to force a single key.
tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

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