TakeHost
← All tutorials

Security

How to Set Up SSH Keys for Secure Server Access

Beginner10 minSSHSecurityed25519Authentication

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.

/01

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]"
/02

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
/03

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
/04

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
/05

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)
/06

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.

Ready when you are

Deploy it on TakeHost.