Password login is the weakest spot of a new server: within minutes of going online, bots start brute-forcing passwords on the SSH port. SSH key authentication cannot be brute-forced, and you no longer have to type a password. This guide covers the whole path: generate a key, put it on the server, test it, and only then disable password authentication.

Tested on Ubuntu 24.04, Ubuntu 26.04 and Debian 12 (server side). Replace 203.0.113.10 with your server's address and root with your user.

How SSH key authentication works

A key is a pair of files. The private key stays on your computer and is never shared. The public key (the file ending in .pub) goes to the server, into ~/.ssh/authorized_keys. When you connect, the server verifies that you hold the private key matching that public key; the private key itself never travels over the network.

Step 1. Generate an SSH key

Windows 10 and 11 ship with the OpenSSH client, so the commands are the same; run them in PowerShell. On macOS and Linux, use the terminal:

ssh-keygen -t ed25519 -C "laptop-john"
  • -t ed25519 is a modern key type: short and strong. Old systems that do not support it are rare today.
  • -C is a comment that tells you later whose key this is. The computer name works well.

The program asks where to save the key. Press Enter to keep the default path (~/.ssh/id_ed25519, on Windows C:\Users\<name>\.ssh\id_ed25519). Then it asks for a passphrase: it encrypts the private key on disk, so if your laptop is stolen, the key cannot be used. Set one.

Step 2. Copy the public key to the server

macOS and Linux

ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.10

The command asks for the server password once and appends the key to ~/.ssh/authorized_keys for you.

Windows

Windows has no ssh-copy-id, so do the same with a single PowerShell command:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh root@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Manually

If you prefer to do it by hand, open id_ed25519.pub on your computer, copy the entire single line (it starts with ssh-ed25519) and run on the server:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys      # paste the line, save: Ctrl+O, Enter, Ctrl+X
chmod 600 ~/.ssh/authorized_keys

Step 3. Test SSH key login

ssh root@203.0.113.10

If the server no longer asks for its password (it may ask for the key passphrase, which is expected), you are done. If it still asks for the server password, the key was not picked up; see the troubleshooting section below.

Step 4. Set up a short host alias in ~/.ssh/config

To avoid typing the address, port and key path every time, add this to ~/.ssh/config on your computer (on Windows, C:\Users\<name>\.ssh\config):

Host myserver
    HostName 203.0.113.10
    User root
    IdentityFile ~/.ssh/id_ed25519

Now ssh myserver is enough. If you change the SSH port later, add a Port <number> line. Other ~/.ssh/config options, copying files and fixing connection errors are covered in How to connect to a server over SSH.

Step 5. Disable SSH password authentication

Do this only after confirming in step 3 that key login works, and keep your current session open until you finish testing: if something goes wrong, you can revert everything through it.

On the server, create a separate config file:

sudo tee /etc/ssh/sshd_config.d/00-keys-only.conf > /dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF

Why a separate file with the 00 prefix: SSH uses the first value it finds for each option and reads the files in sshd_config.d in alphabetical order. Cloud images often include 50-cloud-init.conf with PasswordAuthentication yes; our file is read first and wins. PermitRootLogin prohibit-password allows root to log in with a key only.

Validate the configuration and apply it:

sudo sshd -t                                   # no output means no errors
sudo sshd -T | grep -E 'passwordauthentication|kbdinteractive|permitrootlogin'
sudo systemctl reload ssh                      # on AlmaLinux and CentOS the service is called sshd

sshd -T should show passwordauthentication no and kbdinteractiveauthentication no. For root, Ubuntu 24.04 and Debian 12 print permitrootlogin without-password, which is the old name of the same prohibit-password value. Now connect again in a new terminal window: key login should work. A password login attempt should be rejected:

ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password root@203.0.113.10
# root@203.0.113.10: Permission denied (publickey).

SSH key login not working: troubleshooting

Connect with verbose output; it almost always shows the cause:

ssh -v root@203.0.113.10

Common causes:

Symptom Cause and fix
Permission denied (publickey) right after setup The key is in the wrong file or under the wrong user. Check ~/.ssh/authorized_keys of the exact user you log in as
The key is in place, but the server ignores it Permissions are too open. You need chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys, and the home directory must not be writable by others
The -v output has no Offering public key line The client did not find the key. Specify it explicitly with ssh -i ~/.ssh/id_ed25519 … or add IdentityFile to ~/.ssh/config
Password login is off and the key does not work Log in through the server's web console in your hosting control panel, delete /etc/ssh/sshd_config.d/00-keys-only.conf and run sudo systemctl reload ssh

Next steps

  • Use a separate key for each computer: if you lose a laptop, you only need to delete one line from authorized_keys.
  • Do not send your private key over messengers or keep it in cloud folders without encryption.
  • The next layer of protection is a firewall and automatic blocking of brute-force attempts: initial server setup on Ubuntu (in Russian).
  • A separate key with limited permissions for automated deployment is covered in the article on deploying from GitHub Actions (in Russian).