Disable SSH password authentication

You set PasswordAuthentication no, reloaded sshd, and the server still asks for a password. The setting isn't ignored. Another file set it first.

Why turn passwords off

Any server with port 22 open gets a steady stream of password guesses from bots. With a strong password they will probably never get in, but every guess is a chance, and a reused or leaked password ends it. A key can't be guessed this way. Once passwords are off, those bots get Permission denied (publickey) before they can try anything.

Before you start

Make sure you can already log in with a key, and that everyone else who uses this server can too. Turning passwords off cuts off anyone who still relies on one. If you don't have a key yet, follow SSH keys with ed25519 first.

Know what changes for other users. Anyone without a key in their authorized_keys can no longer log in, and that includes SFTP clients and deploy tools that use a password, because they go through the same sshd. Your provider's web console is not affected: it logs in locally, not over SSH, so a user password still works there. That is also why you should keep one, rather than delete it.

Keep one SSH session open the whole time, and know how to reach your provider's console. Harden SSH without locking yourself out covers the safe routine in detail.

Why the main file loses

Two rules from sshd_config(5) explain almost every "it still asks for a password" report:

Debian and Ubuntu put Include /etc/ssh/sshd_config.d/*.conf at the very top of /etc/ssh/sshd_config. So every drop-in is read before your edit further down the main file, and a drop-in that says yes wins.

On cloud images, that drop-in is usually /etc/ssh/sshd_config.d/50-cloud-init.conf. cloud-init writes it when its ssh_pwauth setting is used, and some providers set that to allow password logins:

$ sudo cat /etc/ssh/sshd_config.d/50-cloud-init.conf
PasswordAuthentication yes

Check the real value with sshd -T

Don't trust what you see in one file. sshd -T prints the settings sshd will actually use after reading every include:

sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin|usepam)'

Then find every file that sets it:

sudo grep -rniE '^\s*(PasswordAuthentication|KbdInteractiveAuthentication)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

Also look for Match blocks in those files. A Match block can turn passwords back on for certain users or addresses. Test a specific connection with sudo sshd -T -C user=deploy,host=your.server.example,addr=203.0.113.10.

Turn passwords off

Create a drop-in that sorts before everything else, so it is read first and wins:

sudo tee /etc/ssh/sshd_config.d/00-no-passwords.conf >/dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
EOF

Why both lines: with UsePAM yes (the Debian and Ubuntu default), PAM can ask for a password through keyboard-interactive authentication even when PasswordAuthentication is off. Debian's default config already sets KbdInteractiveAuthentication no, but stating it here makes the file correct no matter what else changes.

You can also edit 50-cloud-init.conf to say no, but cloud-init may write it again. A file of your own that sorts first doesn't depend on that.

Check and apply:

sudo sshd -t
sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication)'
sudo systemctl reload ssh

Both lines in the output should end in no. If sshd -t prints anything, fix that first and don't reload.

Test a key login in a new terminal before you close your session. If your key isn't actually set up for this user, you will only find out on the next login, and with passwords off the only way back is the provider console.

Test it from outside

From your Mac, a normal login should still work:

ssh [email protected]

Then force a login without keys. It should be refused straight away, with no password prompt:

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

If it still asks for a password, run sshd -T again. Some file or Match block is still setting yes, or the reload didn't happen.

Keep it off

New drop-ins can arrive later: a cloud-init rerun, a provider's agent, a control panel. Recheck with sshd -T after big upgrades or after changing provider settings. If root still logs in directly, also look at PermitRootLogin, and consider moving to a sudo user instead of root. Turning passwords off makes fail2ban less important, but it still cuts down log noise.

Stenvakt checks the value sshd really uses. Its Review reads the effective config, not just the main file, so a drop-in that turns passwords back on shows up. The fix is shown in Preview first and runs in safe mode: if it cuts off SSH, the server rolls it back by itself, and shared-SSH protection won't remove access other people still need. It's a Mac app and isn't out yet: get early access.

Sources

  1. OpenBSD manual: sshd_config(5) (first obtained value, Include, PasswordAuthentication)
  2. OpenBSD manual: sshd(8) (-T)
  3. Debian openssh package: default sshd_config
  4. cloud-init source: ssh_util.py (writes sshd_config.d/50-cloud-init.conf)
  5. cloud-init docs: Set Passwords module (ssh_pwauth)
Next guideFail2ban for SSH