SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

How to Fix SSH Permission denied (publickey) Error

See why SSH show "Permission denied (publickey)". Run ssh -v, read 3 key lines, identify 1 of 5 faults, and fix am without locking yourself out.

What Permission denied (publickey) mean

Permission denied (publickey) mean say your client send one or more public keys, but server no accept any of dem. Network dey okay and sshd dey run: refusal happen for the last step of authentication. The fix no be guesswork, because ssh -v go tell you which of five causes dey affect you.

The words inside the parentheses show the methods wey server ready to accept. Permission denied (publickey) by itself mean password login don off for that server, so no password dey available as fallback. Permission denied (publickey,password) mean passwords dey available, but you fail those ones too.

One message cover five different faults, and e vague intentionally. If server reply "no such user" or "that key is not installed", e go help anybody wey dey scan for valid accounts. So no start changing keys and editing config files. Run one command, read three lines of output, and five possible causes go reduce to one.

Run ssh -v first, then read three lines

Repeat the command wey fail, add -v:

ssh -v deploy@203.0.113.10

A shortened but realistic run fit look like this:

OpenSSH_9.6p1 Ubuntu-3ubuntu13, OpenSSL 3.0.13 30 Jan 2024
debug1: Connecting to 203.0.113.10 [203.0.113.10] port 22.
debug1: Connection established.
debug1: Authenticating to 203.0.113.10:22 as 'deploy'
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:0eL/8sBw... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:0eL/8sBw... agent
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
deploy@203.0.113.10: Permission denied (publickey).

Three lines get everything wey you need.

Authenticating to 203.0.113.10:22 as 'deploy' na the username wey go really dey used. E no be the one wey you intend use: na the one ssh work out from the command line, from ~/.ssh/config, or from your local login name.

Authentications that can continue: publickey na the server list of accepted methods, wey e send before e try any key. If publickey no dey that first list, public key login dey switched off for the server, so no key fit ever work.

Offering public key: ... na one line for each key wey your client really send, showing the file wey e come from and the SHA256 fingerprint. If key no get Offering line, e never reach the server.

Now divide the problem into two:

  • If no Offering public key line dey for the key wey you expect, the fault dey your machine, because the server never see your key at all.
  • If the key dey offered and Authentications that can continue: publickey come back again, the server receive that key but reject am, so the fault dey the server.

The causes below dey arranged according to how often dem turn out to be the answer.

Cause 1: you dey connect with wrong username

The commonest cause na also the least interesting one. sshd, wey be SSH (secure shell) server daemon, no dey tell you when account no exist. E go run the full exchange for made-up username, then reject am for the end with the same message, because exposing valid account names dey help attacker. Typo for username go look exactly like broken key.

Check the Authenticating to ... as line before anything else. If e name your laptop login instead of the server account, you no put username for the command.

ssh -v deploy@203.0.113.10
ssh -v root@203.0.113.10

The default account depend on the image wey your provider build. As of August 2026, Ubuntu cloud images usually release with an ubuntu account, Debian images release with debian or admin, Rocky Linux and AlmaLinux release with rocky and almalinux, while many VPS providers instead install your key directly inside root. Your provider control panel record the account wey e create. No command wey you run from outside the server fit ask am.

A Host block inside ~/.ssh/config also set the username, and e take priority over your local login name:

Host vps-prod
  HostName 203.0.113.10
  User deploy

If na you create the account and later you no fit log in as am, the key probably install for the image default user and you never copy am across. That step dey part of the first ten minutes for a new VPS, and e easy to skip.

Cause 2: key wey you think say you dey send no be the one wey dey send

By default, ssh dey offer only the keys wey ssh-agent dey hold, plus fixed set of filenames for ~/.ssh: id_ed25519, id_ecdsa, id_rsa, and the hardware and DSA variants of those names. If you save key as ~/.ssh/vps-prod, ssh no go see am until you specify the file, na why verbose output no show any Offering public key line for am.

Specify the file, and stop agent keys from taking its place:

ssh -i ~/.ssh/vps-prod -o IdentitiesOnly=yes deploy@203.0.113.10

-i alone no enough when agent dey hold keys, because ssh still dey offer agent keys first and the named file last. This one matter because server dey count every refused key against MaxAuthTries, wey default to 6. Agent wey hold seven keys fit use up the limit before ssh reach your correct key, and the message go then change to:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures

IdentitiesOnly=yes limit the attempt to the file wey you pass. List the keys wey agent dey hold with ssh-add -l, and clear am with ssh-add -D if e don collect old keys for years. Then write the settings down so the next login no depend on remembering flags:

Host vps-prod
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/vps-prod
  IdentitiesOnly yes

One more client-side trap dey. ssh no go use private key wey other accounts for your own machine fit read. E go print warning, then ignore the key, so ssh no go ever offer am and server no go see am:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/you/.ssh/vps-prod' are too open.

chmod 600 ~/.ssh/vps-prod go fix am. Moving key through USB stick or Windows share na the usual way the mode dey get lost. Where keys dey and wetin to call dem dey covered for SSH key management basics.

Cause 3: public key never reach authorized_keys

If ssh -v show say the key dey go out and server still dey refuse am, the next question na whether the key dey inside the account authorized_keys file. Open your provider console to check, because you no fit log in through SSH to inspect am.

sudo ls -l /home/deploy/.ssh/
sudo ssh-keygen -lf /home/deploy/.ssh/authorized_keys

ssh-keygen -lf for an authorized_keys file dey print one fingerprint for each entry:

256 SHA256:0eL/8sBw... you@laptop (ED25519)
3072 SHA256:9Tq2yZk... old-laptop (RSA)

Compare dem with the fingerprint for your Offering public key line. If e no dey the list, the key no dey installed for that account, no matter wetin you remember say you do.

Four ways e fit go wrong, and all of dem common:

  • You paste the private key instead of the .pub file. Public key line dey start with ssh-ed25519 or ssh-rsa. Private key dey start with -----BEGIN OPENSSH PRIVATE KEY-----.
  • The paste wrap enter several lines. Each entry must dey for exactly one line, so system go read wrapped key as several broken entries and nothing go match.
  • The key enter /root/.ssh/authorized_keys while you dey log in as deploy, or na the other way round. The file na for each account, and no shared one dey.
  • Provider "add my key" box write am only to the image default user, so the account wey you create later get empty .ssh directory.

The safe way to add key from the console, as root:

sudo install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
sudo tee -a /home/deploy/.ssh/authorized_keys >/dev/null <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyDataHere you@laptop
EOF
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 600 /home/deploy/.ssh/authorized_keys

Run sudo ssh-keygen -lf /home/deploy/.ssh/authorized_keys again afterwards. The new fingerprint suppose dey the list now. From machine wey fit still log in with password, ssh-copy-id -i ~/.ssh/vps-prod.pub deploy@203.0.113.10 go do the same work and set the modes correctly for you.

Cause 4: why sshd dey ignore authorized_keys when permissions too open

StrictModes yes na the sshd default. Under am, sshd go refuse to read authorized_keys if anybody apart from the owner fit write to that file, the .ssh directory, or the account home directory. The reason direct: if group or everybody fit write to your home directory, any account wey get that access fit replace authorized_keys and take over the login. sshd go treat an untrusted path as if no key dey there.

The client go see the plain Permission denied message. The server log go record the real reason:

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh

or, when na the file itself get problem:

Authentication refused: bad ownership or modes for file /home/deploy/.ssh/authorized_keys

Wetín sshd go accept:

  • The home directory: e no fit be group-writable or world-writable. 755, 750 and 700 all pass. 775 and 777 fail.
  • ~/.ssh: mode 700.
  • ~/.ssh/authorized_keys: mode 600.
  • Ownership: the account wey you dey use to log in must own all three, not root.

Ownership matter as much as the mode. Any file inside /home/deploy/.ssh wey root own go fail the same check. Na this dey happen when you create am with sudo nano and forget to give ownership back. Fix both together:

sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
sudo chmod go-w /home/deploy
ls -ld /home/deploy /home/deploy/.ssh

The last command go show the result. You want drwxr-xr-x or tighter for the home directory, and drwx------ on .ssh. If those strings never clear yet, read how to read permission string like drwxr-xr-x before you change modes on live server.

For Rocky Linux and AlmaLinux, add SELinux (security-enhanced Linux) to the list of things to check. A .ssh directory wey you create through an unusual route fit get the wrong file label, so sshd no go get permission to read am even when the modes look correct. sudo restorecon -Rv /home/deploy/.ssh go restore the labels, and sudo ausearch -m avc -ts recent go show whether SELinux na the component wey refuse the access.

Cause 5: sshd don configure to reject you

To read /etc/ssh/sshd_config alone no dey enough for current Ubuntu or Debian system. That file start with Include /etc/ssh/sshd_config.d/*.conf, and OpenSSH dey keep the first value wey e find for any setting. So, e go read drop-in file like 50-cloud-init.conf first, and that value go override anything wey you edit lower down inside the main file. Na why edit fit look correct but e no change anything.

Ask sshd which configuration e really dey use:

sudo sshd -T | grep -Ei 'pubkeyauth|authorizedkeysfile|permitrootlogin|allowusers|allowgroups|denyusers'

Healthy answer go look like this:

permitrootlogin prohibit-password
pubkeyauthentication yes
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2

Things wey you suppose check for your own output:

  • pubkeyauthentication no. No key go ever dey accepted. This one also dey show for ssh -v as first Authentications that can continue: list wey no get publickey inside.
  • authorizedkeysfile dey point to another place, for example /etc/ssh/authorized_keys/%u. Your file for the home directory go then dey completely ignored, and mode rules from cause 4 go apply to the new path instead.
  • allowusers or allowgroups dey present. Any account wey no dey listed go dey rejected with exactly this error and no explanation. denyusers and denygroups dey do the reverse.
  • permitrootlogin no dey present while you dey try log in as root. prohibit-password na the useful middle setting: root fit use key but no fit use password.

Match blocks no dey appear for plain sshd -T, because their result depend on who dey connect. Ask about one specific connection:

sudo sshd -T -C user=deploy,host=vps.example.com,addr=198.51.100.7

One more setting dey affect older keys. OpenSSH 8.8 stop accepting SHA-1 signatures (ssh-rsa) by default, so RSA key wey work for years fit stop working immediately after server upgrade. The client go talk am clearly:

debug1: send_pubkey_test: no mutual signature algorithm

The correct fix na to create new key: ssh-keygen -t ed25519 -C "deploy@vps-prod", then install the .pub file as shown above. Setting PubkeyAcceptedAlgorithms +ssh-rsa for the server go enable the old signatures again and give you access today, so treat am as temporary way to reach the box, not as the end of the work. The remaining server-side settings wey worth reviewing dey for hardening SSH server for VPS.

Wetin you fit use prove say private key match the public key wey you install

Most of the guesswork for this error dey come from not knowing whether two files be pair. One command go answer am:

ssh-keygen -y -f ~/.ssh/vps-prod

This go print the public key wey e derive from the private key. E no ever read the .pub file wey dey beside am, so e dey show wetin the private key really be, instead of wetin stale .pub file claim. If the key get passphrase, the command go ask for am. This one still prove say you know the passphrase.

ssh-keygen -lf ~/.ssh/vps-prod.pub
ssh-add -l

The first command go print the fingerprint of one public key file. The second one go print the fingerprints wey your agent dey hold. Now compare four views of the same string: the fingerprint for the Offering public key line from ssh -v, the fingerprint of your .pub file, the fingerprints inside ssh-keygen -lf for the server's authorized_keys, and the fingerprint inside the server log. The place wey dem stop matching na where the problem dey.

Log monitɔ di server while login dey fail

The client no dey receive useful information on purpose. Na server dey write the real reason. Start log follower for console session, then run the failing ssh command from your laptop.

sudo journalctl -u ssh -f

Ubuntu 24.04 no dey install rsyslog by default, so /var/log/auth.log fit no dey there. For Rocky Linux and AlmaLinux, the unit name na sshd, and the same records dey also enter /var/log/secure.

Set LogLevel VERBOSE for sshd configuration, then reload the service. Every attempt go then log the fingerprint wey server actually receive:

Failed publickey for deploy from 198.51.100.7 port 49812 ssh2: ED25519 SHA256:0eL/8sBw...

That line go show you which side get the fault. If you recognise the fingerprint, e mean say your key reach server but server reject am, so check causes 3, 4 and 5. If you no recognise the fingerprint, e mean say your client send key wey you no intend to use, so go back to cause 2.

If the log still no clear, run another sshd for different port with debug mode. E go stay for foreground, serve one connection, print the reason for the decision, then exit:

sudo /usr/sbin/sshd -ddd -p 2222

From console session for the same server, connect to am through loopback address:

ssh -p 2222 -i ~/.ssh/vps-prod -o IdentitiesOnly=yes deploy@127.0.0.1

Using 127.0.0.1 keeps firewall out of the test. The debug output go show the file wey e open, the fingerprint wey e compare, and the exact reason for refusal, including lines like Authentication refused: bad ownership or modes for directory /home/deploy. Press Ctrl+C when you don get the answer. The real sshd for port 22 no go change throughout.

How to avoid locking yourself out

Every step wey edit server configuration need get another way to enter wey no depend on SSH. Set am up while SSH still dey work, no be after e don break.

  1. Open your provider's console through serial or VNC (virtual network computing), then confirm say you fit log in there.
  2. Make sure say you know working local password for account wey get sudo. If you no get one, reset the root password from the provider console first.
  3. Keep your current SSH session open. Open session dey survive systemctl restart ssh, so e go remain as way to enter back if the new config no correct.
  4. Check the syntax before you restart: sudo sshd -t no print anything when the file valid, and e print the file plus line number when e no valid.
  5. Open second terminal and log in fresh before you close the first one. Broken config dey stop new logins but e leave existing ones alone, so the session wey you dey use no fit tell you whether the change work.

Restart with sudo systemctl restart ssh for Debian and Ubuntu, or sudo systemctl restart sshd for Rocky Linux and AlmaLinux. For Ubuntu 24.04, sshd dey start from socket unit, so any change to Port or ListenAddress also need sudo systemctl restart ssh.socket before e go take effect.

FAQ

Why I dey get Permission denied (publickey) when the same key dey work for another server?

Because the key dey okay, but something around am no dey okay. Run ssh -v and find the Offering public key line. If your key no dey listed, ssh never send am: the file no dey inside ~/.ssh under a default name and e no dey loaded for the agent, so add -i /path/to/key -o IdentitiesOnly=yes. If the key dey listed and the server still reject am, that key no dey inside the account's authorized_keys, the path to am dey writable by group, or sshd config block the user. Server log go show which one happen.

How I fit see which key SSH actually dey send?

ssh -v host dey print one debug1: Offering public key: line for each key, and each line name the source file plus SHA256 fingerprint. ssh-add -l dey list the fingerprints wey the agent hold. ssh-keygen -lf ~/.ssh/id_ed25519.pub dey print the fingerprint of one key file, while ssh-keygen -y -f ~/.ssh/id_ed25519 dey print the public key wey one private key really derive. For login to work, the fingerprint from the Offering line must also appear for ssh-keygen -lf when you run am against the server's authorized_keys.

Why sshd dey ignore my authorized_keys file?

Because StrictModes dey on by default, and either the file, the .ssh directory, or the home directory dey writable by group or world, or the wrong account own am. sshd no go trust path wey another person fit change, so e go behave as if no key exist. Set the home directory to 755 or tighter, .ssh to 700, authorized_keys to 600, and make sure the login account own all three. With LogLevel VERBOSE the server go record Authentication refused: bad ownership or modes for directory /home/deploy/.ssh.

My key stop working immediately after server upgrade. Wetin change?

If na RSA key, this one most likely na the SHA-1 change. OpenSSH 8.8 disable ssh-rsa SHA-1 signatures by default, so any key wey fit sign only that way go dey rejected now. The verbose client output go show debug1: send_pubkey_test: no mutual signature algorithm. Generate modern key with ssh-keygen -t ed25519 and install its .pub file. If you need access immediately, PubkeyAcceptedAlgorithms +ssh-rsa for the server go enable the old signatures again, and you suppose remove that line once the new key dey work.

I edit sshd_config and now I no fit log in at all. How I fit enter again?

Use your provider's console, because SSH no dey pass through there. Log in there with local password, run sudo sshd -t to see the syntax error and the line number, undo the change, then restart the service. After that check sudo sshd -T to confirm the values wey dey run, because file inside /etc/ssh/sshd_config.d/ fit dey override the main config. If you no get local password, reset the root password from the console first, then repair the file.