Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Troubleshooting

SSH Permission Denied: Publickey, Password, and the Real Cause

Sean

Platform Writer

Jul 05, 2026
7 min read

Permission denied from SSH has two flavors: (publickey) means the server reached public-key auth and found no match; (password) means the server is not even accepting passwords. The fix is different for each. The team that reads the parenthetical correctly resolves the issue in one shot - the team that confuses them spends 30 minutes chasing the wrong setting.

SSH Permission Denied: Publickey, Password, and the Real Cause

Table of contents

Publickey denied: the eight checks

The full checklist is in the SSH public key denied post. Quick recap:

  1. Public key in server’s ~/.ssh/authorized_keys.
  2. Server-side ~/.ssh is 700, authorized_keys is 600.
  3. Server’s sshd_config has PubkeyAuthentication yes.
  4. Client’s id_ed25519 is 600.
  5. Client is sending the right key (check with ssh -v).
  6. Logging in as the correct user.
  7. Home directory is readable (not NFS-mounted with bad perms).
  8. SELinux/AppArmor context is right (RHEL/Fedora family).

The team that walks through these in order finds the issue on the first or second check 90% of the time. The team that skips ahead to step 8 first is wasting time.

Password denied: why the server is not offering password auth

Permission denied (password) means the server has password auth disabled. That is the modern default on most Linux distros after OpenSSH 7+, and the right setting for any production server. The fix is not to re-enable password auth - it is to set up key-based auth instead.

The server’s sshd_config:

PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes

That triplet is the modern hardening. The team that sees Permission denied (password) on a server with this config needs to add their public key to authorized_keys, not negotiate password back on.

The user-typed-wrong-password case

If PasswordAuthentication yes is set and the user is still denied, the password is wrong. Three causes:

  1. Caps Lock or Num Lock.
  2. Wrong user (the team that types their laptop password instead of the server password).
  3. The server has a recent password change that did not propagate.

The team that uses sshpass -p (for scripts) or stores the password in a password manager has fewer of these. The team that copies passwords from a chat window misses the leading character more often than they think.

The host key warning

A different permission denied pattern: Host key verification failed. The server’s host key (not the user’s key) does not match the cached entry:

REMOTE HOST IDENTIFICATION HAS CHANGED!
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

That is a real security warning. The team that ignores it and re-keys known_hosts is rolling the dice - if the change is a legitimate one (server reinstall, IP reassignment), the re-key is fine. If it is a man-in-the-middle, the re-key has just compromised the connection.

The right workflow: verify out-of-band with the server admin that the host key changed. Then ssh-keygen -R server.example.com removes the old entry. The team that documents host keys in their infra-as-code (Terraform known_hosts_file) never sees this warning because the file is reproducible.

The ‘no matching key’ verbose output

ssh -vvv user@server is the verbose debugging view:

debug1: Offering public key: /Users/you/.ssh/id_ed25519
debug3: send_pubkey_test: no signature match
debug1: No more authentication methods to try.

No signature match means the server saw the key, tried to verify the signature, and the signature did not match. That is the public-key-was-recognized-but-rejected case - check the user’s home directory, the perms on authorized_keys, and the key’s content (one missing character in the .pub file is enough to fail the signature).

The team that uses -vvv and copies the right log lines into a search engine finds a Stack Overflow answer 80% of the time. The team that just retries with no debugging does not.

The connection refused case

ssh: connect to host server port 22: Connection refused is a different problem: the server is not listening on port 22. That is not a permission issue at all - the daemon is not there.

Causes:

  • sshd is not running: sudo systemctl status ssh.
  • Firewall is blocking: sudo ufw status or sudo iptables -L.
  • Wrong port: the server’s sshd_config has Port 2222 but the client is using 22.
  • Wrong host: the IP or DNS does not resolve.

The team that confuses connection refused (no daemon) with permission denied (daemon rejected auth) is debugging in the wrong file.

FAQ

What does ‘Permission denied (publickey)’ actually mean?

The server reached public-key authentication, found no matching key for the user, and rejected the connection. The fix is in the server’s authorized_keys or the client’s key file, not in the password settings.

How do I re-enable password authentication?

Set PasswordAuthentication yes in /etc/ssh/sshd_config and sudo systemctl reload sshd. The team that does this on a production server should have a good reason - public-key is strictly safer.

Why does the user account get locked out?

Some PAM configurations lock accounts after too many failed attempts. faillock --user <name> --reset (RHEL family) or pam_tally2 --user <name> --reset (older distros) clears the count. The team that uses fail2ban or similar sees IP-based blocks, not user-account blocks.

What is the difference between authorized_keys and known_hosts?

authorized_keys is on the server and lists public keys allowed to log in. known_hosts is on the client and lists server host keys the client trusts. They are unrelated - the first is what keys can log in here and the second is what servers have I verified before.

Can I see who last logged in?

On the server: last -n 20 or lastlog. On the client: ~/.ssh/known_hosts has the host key history but not login times. The team that audits SSH access uses /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL family) with grep sshd.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#ssh#troubleshooting#permissions#dev-infra