Security
How to Set Up SSH Keys for Secure Server Access
SSH keys are far stronger than passwords and cannot be brute forced. This guide uses a modern ed25519 key, confirms key login works in a second terminal before locking anything down, and finishes by hardening the SSH daemon. The order matters: never disable password login until you have proven key login works, or you can lock yourself out.
Generate an ed25519 Key Pair
On your LOCAL machine, generate an ed25519 key. It is fast, compact, and the current best practice. Always set a passphrase so a stolen key file is useless on its own.
# -t ed25519 selects the modern elliptic-curve algorithm (preferred in 2026) # -a 100 applies 100 rounds of KDF hardening to the private key on disk # -C is just a comment to help you identify the key later ssh-keygen -t ed25519 -a 100 -C "[email protected]" # When prompted, enter a strong passphrase (do not leave it empty) # Legacy fallback only if a device cannot do ed25519: ssh-keygen -t rsa -b 4096 -a 100 -C "[email protected]"
Copy the Public Key to the Server
Use ssh-copy-id to install your PUBLIC key into the server's authorized_keys. This still uses your password this one time.
# Installs ~/.ssh/id_ed25519.pub into the server's ~/.ssh/authorized_keys ssh-copy-id username@your_server_ip
Verify Key Login in a SECOND Terminal
Open a NEW terminal and log in with the key while keeping your current session open. You should get in without typing the account password (only your key passphrase, if your agent has not cached it). Do not proceed until this works.
# In a brand new terminal window (keep the old one open as a safety net): ssh username@your_server_ip # Success = you reach a shell prompt without being asked for the ACCOUNT password
Disable Password and Root Login
Only now, edit the SSH config to require keys and block direct root login. Use a drop-in file so package updates do not overwrite your changes.
# Create a drop-in override (cleaner than editing sshd_config directly) sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<EOF PasswordAuthentication no # keys only, no passwords accepted KbdInteractiveAuthentication no # block keyboard-interactive password fallback PermitRootLogin no # never allow direct root SSH login EOF # Validate the config BEFORE reloading so a typo cannot lock you out sudo sshd -t
Reload SSH and Confirm Lockdown
Reload the daemon, then verify from a new terminal that key login still works and password login is refused.
sudo systemctl reload ssh # reload (not restart) keeps your current session alive # From a new terminal, confirm keys still work: ssh username@your_server_ip # Confirm passwords are now rejected: ssh -o PubkeyAuthentication=no username@your_server_ip # should say: Permission denied (publickey)
Add Brute-Force Protection with fail2ban
Install fail2ban so the few remaining connection attempts that hit your server get banned after repeated failures. This is a strong final layer.
sudo apt update && sudo apt install -y fail2ban sudo systemctl enable --now fail2ban # start now and on every boot sudo fail2ban-client status sshd # verify the sshd jail is active
Your server now accepts ed25519 key logins only, refuses passwords and direct root access, and bans repeat offenders with fail2ban. Keep your private key passphrase-protected and never copy the private key to an untrusted machine.