SSH Keys Explained: Generating, Using, and Not Losing Them
Every internet-facing SSH server receives a constant stream of automated login attempts. Not targeted attacks, just botnets working through address space trying common usernames and passwords. If your server accepts passwords, you are relying on nobody ever guessing one. Key authentication removes that bet entirely.
What a key pair actually is
An SSH key is two mathematically related files. The private key stays on your machine. The public key goes on every server you want to reach.
When you connect, the server sends a challenge. Your client signs it with the private key. The server verifies the signature against the public key it already has. The private key itself is never transmitted, which is the entire point: there is nothing to intercept, and a compromised server learns nothing that lets it impersonate you elsewhere.
That last property is worth dwelling on. With passwords, logging into a compromised server hands the attacker a credential that probably works somewhere else too. With keys, they get a signature over a challenge they chose, which is useless.
Generating a key
ssh-keygen -t ed25519 -C "you@yourmachine"
That is the whole command. The -C comment is a label that ends up in the public key, and using something identifying like laptop-2026 makes it far easier later to work out which line in an authorized_keys file you can safely delete.
You will be asked for a file location, where the default ~/.ssh/id_ed25519 is right unless you are creating a second key, and for a passphrase.
Why Ed25519
Ed25519 is the default recommendation and has been for years. It is fast, the keys are short enough to read, and there are no size or curve parameters to get wrong.
RSA still works and remains necessary for some older systems. If you need it, use 4096 bits:
ssh-keygen -t rsa -b 4096 -C "you@yourmachine"
ECDSA exists and there is no strong reason to choose it over Ed25519. DSA is obsolete, removed from modern OpenSSH entirely, and if something still requires it that system has larger problems.
The passphrase question
An unencrypted private key is a file that grants access to your servers to anyone who obtains it: a stolen laptop, a backup on a shared drive, a misconfigured sync client.
A passphrase encrypts the key at rest. The obvious objection is that typing it constantly defeats the convenience, which is what ssh-agent solves.
ssh-agent
The agent holds decrypted keys in memory and answers signing requests, so you enter the passphrase once per session instead of once per connection.
# Most desktops start an agent automatically. If not:
eval "$(ssh-agent -s)"
# Add your key
ssh-add ~/.ssh/id_ed25519
# What is loaded right now?
ssh-add -l
# Drop everything, for example before walking away
ssh-add -D
Set a lifetime so keys do not stay loaded indefinitely:
ssh-add -t 8h ~/.ssh/id_ed25519
Agent forwarding, carefully
ssh -A forwards your agent to the remote host so you can hop onward without copying keys there. It is convenient and it hands the remote machine the ability to ask your agent to sign anything, for as long as you are connected. Anyone with root on that host can use your keys.
Two safer options. Use ProxyJump instead, which tunnels through the intermediate host without exposing your agent:
ssh -J bastion.example.com user@internal-host
Or scope the key to specific destinations when adding it:
ssh-add -h internal-host.example.com ~/.ssh/id_ed25519
That destination restriction is enforced by the agent, and OpenSSH 10.5 fixed a bug where a locked agent handled those restrictions incorrectly, which is a good reason to be current.
Getting the key onto a server
ssh-copy-id user@host
This appends your public key to ~/.ssh/authorized_keys on the remote machine and sets the permissions correctly. You will authenticate with your password one final time.
Doing it manually is fine as long as you get the permissions right, because sshd will silently refuse a key from a file it considers too open:
ssh user@host "mkdir -p ~/.ssh && chmod 700 ~/.ssh"
cat ~/.ssh/id_ed25519.pub | ssh user@host "cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
The home directory itself must also not be group writable. This is the single most common cause of “my key is being ignored,” and the server log tells you plainly:
sudo journalctl -u sshd -n 30
Turning passwords off
Once keys work, and only once you have confirmed they work in a second terminal you have not closed, disable password authentication.
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
sudo sshd -t # validate before restarting
sudo systemctl restart sshd
Keep the working session open until you have proved a new one connects. Locking yourself out of a remote server is entirely avoidable and extremely annoying.
Our SSH hardening guide covers the rest of the configuration, and the SSH config builder generates per-host blocks.
Managing more than one key
Once you have several keys, ~/.ssh/config is what keeps it manageable:
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
Host prod-*
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
IdentitiesOnly yes
ServerAliveInterval 60
IdentitiesOnly yes matters more than it looks. Without it, SSH offers every key the agent holds, in order, and a server with MaxAuthTries 3 may disconnect you before reaching the right one. The symptom is a login that fails despite the correct key being loaded.
OpenSSH 10.5 added a flag that makes this diagnosable in one step:
ssh -Z user@host # print the keys SSH would offer, in order
Backing keys up, and revoking them
A private key is not recoverable. Lose it and you lose access to every server that trusted it, which on a cloud instance you cannot console into may mean rebuilding.
Back the private key up somewhere encrypted, a password manager or an encrypted volume, not a cloud folder that syncs in plaintext.
Revocation is manual: remove the corresponding line from authorized_keys on every server. This is exactly why the -C comment is worth setting, and why per-purpose keys are worth the small extra effort.
grep -n "laptop-2026" ~/.ssh/authorized_keys
Hardware keys
A FIDO security key stores the credential in hardware that cannot export it, so a compromised machine cannot steal it.
ssh-keygen -t ed25519-sk -C "yubikey"
The -sk suffix means the private key lives on the token. Authentication requires physically touching it, so a remote attacker on your laptop cannot use it while you are away from the desk. For anything genuinely sensitive this is the strongest option available and the setup cost is one command.
Frequently Asked Questions
Which SSH key type should I generate?
Ed25519. It is fast, produces short keys, has no parameter choices to get wrong, and is supported by every current SSH implementation. Use RSA at 4096 bits only when you must talk to something too old to accept Ed25519.
Should I put a passphrase on my SSH key?
Yes. The private key is a file, and a file can be copied off a stolen laptop or a compromised backup. A passphrase encrypts it at rest. Use ssh-agent so you type the passphrase once per session rather than once per connection.
What is the difference between the two files ssh-keygen creates?
The file without an extension is your private key and must never leave the machine. The .pub file is the public key, which is safe to publish anywhere and is what you copy to servers. Anything that asks you to paste a private key is either mistaken or malicious.
How do I copy my key to a server?
ssh-copy-id user@host does it correctly, appending your public key to the remote authorized_keys file with the right permissions. Doing it by hand works too but the permissions are easy to get wrong, and sshd silently ignores files it considers too permissive.
Why is my key being ignored by the server?
Permissions, almost every time. The remote .ssh directory must be 700 and authorized_keys must be 600, and the home directory must not be group writable. sshd refuses keys from loosely permissioned files without telling you why. Check the server log with journalctl -u sshd.
Can I use one key for every server?
You can, and many people do. Separate keys per purpose limit the blast radius if one is compromised and let you revoke access to one place without touching others. At minimum keep work and personal keys separate.