Every server with SSH on the internet gets password-guessing attempts within minutes of going online. Disabling password authentication and allowing only SSH keys stops that whole class of attack. Bots can guess passwords, but they can’t guess a private key. It’s the single most effective SSH hardening step. Here’s how to do it without locking yourself out.
1. Have a key on your computer
ls ~/.ssh/id_ed25519.pub || ssh-keygen -t ed25519 -C "you@laptop"
Use a passphrase on the key, and ssh-agent so you type it once per session. See ssh-keygen and SSH agent.
2. Install the public key on the server
ssh-copy-id [email protected]
Without ssh-copy-id (on Windows, for example):
cat ~/.ssh/id_ed25519.pub | ssh [email protected] 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
Permissions matter. sshd ignores keys if ~/.ssh or authorized_keys is writable by others:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
3. Test key login in a new terminal
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no [email protected]
If this logs you in without a password prompt, key auth works. Don’t continue until it does. If you’ll use sudo, check that too: sudo -v.
4. Disable password authentication
Use a drop-in file. Ubuntu, Debian and RHEL include Include /etc/ssh/sshd_config.d/*.conf at the top of sshd_config:
sudo tee /etc/ssh/sshd_config.d/10-keys-only.conf > /dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
EOF
PermitRootLogin prohibit-password allows root only with keys. Use no if you log in as a normal user with sudo. See disable root SSH login.
Watch for files that override yours
sshd uses the first value it reads for each setting. Some images ship drop-ins that enable passwords, such as cloud-init’s 50-cloud-init.conf with PasswordAuthentication yes. Because 10-… sorts first, your file wins. Check what sshd will actually use:
grep -ri passwordauthentication /etc/ssh/sshd_config /etc/ssh/sshd_config.d/
sudo sshd -T | grep -E 'passwordauthentication|kbdinteractive|permitrootlogin|pubkeyauthentication'
sshd -T prints the effective configuration, which is the definitive check.
5. Validate and reload
sudo sshd -t && sudo systemctl reload ssh # 'sshd' on RHEL family
Keep your current session open. In a new terminal, test again:
ssh [email protected] # should work with the key
ssh -o PubkeyAuthentication=no [email protected] # should now FAIL: "Permission denied (publickey)"
Locked out?
Use your provider’s VNC console. It’s a local login that doesn’t go through SSH. Log in with the user’s password at the console, then fix authorized_keys or the sshd config. VPS.DO includes a VNC console in the control panel for every VPS. See Linux rescue mode.
Make sure the account has a password set (sudo passwd user), even if SSH doesn’t accept passwords. You’ll need it for the console and for sudo.
Managing keys for teams
- One key per person and per device. Remove a key from
authorized_keyswhen someone leaves or a laptop is lost. - Add comments (
ssh-ed25519 AAAA… alice@laptop-2026) so you know which key is whose. - Restrict keys used by automation:
from="10.0.0.5",command="/usr/local/bin/backup-receive",no-pty,no-port-forwarding ssh-ed25519 AAAA… backup@server2
- For larger setups, consider SSH certificates or centralised key management (Ansible, an identity provider).
Extra layers
Key-only auth stops brute-force attacks, but these still help:
- Fail2Ban or CrowdSec to ban scanners and reduce log noise. See Fail2Ban.
- Firewall SSH to known IPs where possible, or use a VPN or bastion. See ProxyJump.
- Two-factor on top of keys for high-value servers. See SSH 2FA.
- Changing the port reduces noise, but isn’t security on its own. See change SSH port.
Quick reference
| Step | Command |
|---|---|
| Create key | ssh-keygen -t ed25519 |
| Install key | ssh-copy-id user@host |
| Test key-only | ssh -o PasswordAuthentication=no user@host |
| Disable passwords | PasswordAuthentication no + KbdInteractiveAuthentication no |
| Effective config | sudo sshd -T | grep passwordauthentication |
| Apply | sudo sshd -t && sudo systemctl reload ssh |
Related: SSH permission denied (publickey) and Linux server hardening.