SSH

Switch a server to SSH key login

Create an Ed25519 key, install it on the server, prove that it works in a second session, and only then turn password login off with a drop-in file that sshd reads before anything else.

Written againstOpenSSH 9.2 (Debian 12)OpenSSH 9.6 (Ubuntu 24.04)OpenSSH 8.7 (RHEL 9)
Reading time
4 min
Commands to copy
10
Last checked
24 Oct 2026

A key pair replaces the password with two files: a private key that stays on your machine and a public key that goes on the server. A key can’t be guessed the way a password can, and a server that accepts only keys shuts out the bots that scan port 22 and try common passwords. The order matters here: the key has to work before passwords are turned off, or the next login fails.

Create a key on your machine

Run this on the computer you connect from, not on the server. Ed25519 keys are short, fast to check, and supported by every OpenSSH release since 6.5. The comment after -C is only a label, so put something in it that tells you later where the key lives.

shell
$ ssh-keygen -t ed25519 -C "you@laptop, 2026-10"Generating public/private ed25519 key pair.# trimmed: the prompts for the file name and the passphraseYour identification has been saved in /home/you/.ssh/id_ed25519Your public key has been saved in /home/you/.ssh/id_ed25519.pub

Give the key a passphrase. Without one, anybody who copies id_ed25519 off your laptop can log in as you. With one, the file is encrypted, and ssh-add loads it into the agent once per session so you don’t type the passphrase on every connection.

FileWhat it isWhere it goes
~/.ssh/id_ed25519The private keyStays on your machine, mode 600. Never copy it to a server.
~/.ssh/id_ed25519.pubThe public key, one line of textInto ~/.ssh/authorized_keys on every server you log in to

Install the public key on the server

ssh-copy-id logs in with your password one last time and appends the public key to ~/.ssh/authorized_keys on the server, creating the directory with the right permissions if needed.

shell
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]# trimmed: the INFO lines and the password promptNumber of key(s) added: 1

Windows doesn’t ship ssh-copy-id. From any machine without it, pipe the key into the same file yourself:

shell
$ cat ~/.ssh/id_ed25519.pub | ssh [email protected] 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

Test the key in a second session

Keep the session you already have open, and open a second terminal. These options make the client try the key and nothing else, so a silent fallback to the password can’t make a broken key look like it works:

shell
$ ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no [email protected]$ ssh -v [email protected] true 2>&1 | grep Authenticateddebug1: Authenticated to 192.0.2.10 ([192.0.2.10]:22) using "publickey".

If the first command asks for a password or ends in Permission denied, fix the key before you go on.

Turn password login off

On all three distributions, an Include line near the top of /etc/ssh/sshd_config reads every file in /etc/ssh/sshd_config.d/ ending in .conf, in alphabetical order. For each setting, sshd keeps the first value it reads and ignores the rest. A setting further down in sshd_config loses to any drop-in file, and a drop-in file loses to one that sorts before it.

That’s why the file below starts with 10-. Ubuntu cloud images and other cloud-init installs often have /etc/ssh/sshd_config.d/50-cloud-init.conf with PasswordAuthentication yes in it. Edit sshd_config alone and that line keeps passwords on.

  1. Write the drop-in file

    /etc/ssh/sshd_config.d/10-keys-only.conf
    # Keys only. Sorts before 50-cloud-init.conf, so these values win.PasswordAuthentication noKbdInteractiveAuthentication noPermitRootLogin prohibit-password

    KbdInteractiveAuthentication closes the second way a password can be asked for (through PAM). On OpenSSH before 8.7 it was called ChallengeResponseAuthentication. prohibit-password lets root in with a key only, which is the default since OpenSSH 7.0. Set it to no if nobody logs in as root at all.

  2. Check the configuration

    shell
    $ sudo sshd -t$ sudo sshd -T | grep -i passwordauthenticationpasswordauthentication no

    sshd -t prints nothing when the files are valid. sshd -T prints the values sshd will use after reading every file, so it shows whether another drop-in still wins.

  3. Reload sshd

    shell
    # Debian and Ubuntu$ sudo systemctl reload ssh# RHEL 9$ sudo systemctl reload sshd

    A reload applies to connections made after it. The session you’re typing in stays open.

  4. Prove that passwords are refused

    shell
    $ ssh -o PubkeyAuthentication=no [email protected][email protected]: Permission denied (publickey).

    The list in brackets is what the server still accepts. publickey alone is the result you want. On RHEL it also lists the GSSAPI methods that 50-redhat.conf turns on.

Next steps

Last checked on 24 October 2026 against OpenSSH 9.2 (Debian 12), OpenSSH 9.6 (Ubuntu 24.04), and OpenSSH 8.7 (RHEL 9). If a step doesn’t match what you see, contact us with the command and what it printed.