SSH: authentication via private/public keys
SSH authentication by password works, but it is weak: the password is typed at every connection, it can be brute-forced (fail2ban mitigates but does not solve) and it does not distinguish “who” from “what”. SSH keys solve all three: the private key proves identity, the public key authorizes access and once configured, no more password.
Generate the pair
ssh-keygen -t rsa -b 4096 -C "comment"
The -t rsa generates an RSA pair, the -b 4096 sets the size (2048 minimum, 4096 recommended). The -C is a free comment (usually the email or hostname). Two files: id_rsa (the private key, never leaves the workstation) and id_rsa.pub (the public key, to copy to servers).
Deploy the public key
ssh-copy-id user@server
This command copies the content of id_rsa.pub into ~/.ssh/authorized_keys on the server (chmod 600, .ssh 700). It can also be done manually:
cat ~/.ssh/id_rsa.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"
Once deployed, the connection happens without a password:
ssh user@server
The SSH agent
The private key passphrase can be cached by ssh-agent:
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
The passphrase is asked once, then the agent signs connections without asking again. With keychain, the agent persists between sessions (it stores the socket in a file that subsequent shells reuse).
Disabling password authentication
Once all keys are deployed, you can close the door:
# /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
/etc/init.d/ssh restart
At this point, only holders of the private key can connect. Password brute-force no longer works (there is no password). The SSH server goes from “accessible by anyone with a password” to “accessible by whoever has the key”. This is the biggest security upgrade for an SSH server and it takes 5 minutes.
The authorized_keys concept
The ~/.ssh/authorized_keys file contains one public key per line. Each line authorizes access for the corresponding private key. Each line can be restricted:
command="/usr/bin/rsync --server --daemon .",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...
This line authorizes ONLY rsync (no shell, no port forwarding, no X11, no terminal). This is the secure backup mechanism: the backup machine has a key that can only do one thing.
[edit: 2026] SSH keys are still the standard authentication mechanism, Ed25519 has replaced RSA as the default choice and SSH certificates (ssh-keygen -s) have added an expiration and revocation layer. The PasswordAuthentication no remains the first thing to do on a fresh SSH server. SSH rootkits that hook PAM still exist and the defense remains the same: password disabled, keys only and an audit of authorized_keys (they accumulate and nobody cleans them).
[edit: 2026] The Ansible implementation of all this: the ssh role .