Fix SSH Permission Denied (publickey) Error

TL;DR: permission denied (publickey) means SSH couldn't match your private key to an authorized public key on the server. Most common causes: your public key isn't in ~/.ssh/authorized_keys, file permissions are wrong, or PubkeyAuthentication is disabled in sshd_config. Run ssh -vvv first — the debug output tells you exactly where the handshake fails.

Start here: run SSH in verbose mode

Before touching any config file, run the connection with verbose output:

ssh -vvv user@server

Look for lines like these in the output:

debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
user@server: Permission denied (publickey).

"No more authentication methods to try" means the server either didn't receive your key offer or found no match in authorized_keys. If you see "Server accepts key" but still get denied, the problem is almost always permissions or a SELinux context on the server side. Either way, verbose mode gives you a specific line to act on rather than a guess.

Fix 1: your public key isn't in authorized_keys

This is the most common cause by far. The easiest fix is ssh-copy-id:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

It appends your public key to ~/.ssh/authorized_keys on the server and sets the correct permissions on ~/.ssh automatically. You'll need password authentication still working on the server for this step — if it's already been disabled, you'll need another way in first (cloud console, secondary key, or a recovery session).

On macOS, ssh-copy-id isn't bundled by default. Install it with brew install ssh-copy-id, or copy the key manually:

cat ~/.ssh/id_ed25519.pub | ssh user@server \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
   cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

After either method, confirm the key actually landed:

ssh user@server "cat ~/.ssh/authorized_keys"

Fix 2: wrong permissions on .ssh files and directories

sshd defaults to StrictModes yes, which means it silently refuses to use authorized_keys if the file or its parent directories are group-writable or world-writable. It won't log a helpful error on the client side — it just drops the key and moves on.

On the server

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh

On the client

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Also check the home directory itself:

ls -ld ~

If it shows group-writable or world-writable — e.g. drwxrwxr-x — sshd rejects everything in it regardless of what authorized_keys looks like. Fix it with chmod 755 ~. I've watched a developer run chmod -R 777 /home to "fix a permissions problem" on a shared dev server and break SSH for every user on the box in one command.

Fix 3: PubkeyAuthentication disabled in sshd_config

Some hardened builds, cloud images, and enterprise templates ship with public key authentication commented out or explicitly set to no. Check it:

grep -E "PubkeyAuthentication|AuthorizedKeysFile" /etc/ssh/sshd_config

You want:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

If you make a change, test for syntax errors before restarting:

sudo sshd -t

Then restart the daemon. The service name differs by distro:

# Ubuntu / Debian
sudo systemctl restart ssh

# RHEL / CentOS / Fedora
sudo systemctl restart sshd

While you're in sshd_config, also check the AuthorizedKeysFile path. Some enterprise configs redirect it to something like /etc/ssh/authorized_keys/%u. If your key is sitting in ~/.ssh/authorized_keys but sshd is looking in a centralized directory, it'll never find it.

Fix 4: old RSA key rejected by OpenSSH 8.8+

Since OpenSSH 8.8 — which ships in Ubuntu 22.04, RHEL 9, Fedora 33, and later — the legacy ssh-rsa signature scheme (RSA signing with SHA-1) is disabled by default. A key generated a few years ago can trigger this error even when everything else looks perfectly correct.

Check the server's auth log for this specific message:

# Ubuntu / Debian
journalctl -u ssh --since -1h | grep Pubkey

# RHEL / CentOS / Fedora
journalctl -u sshd --since -1h | grep Pubkey
# or: sudo tail /var/log/secure

If you see this, that's the cause:

userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

The right fix is to generate a new Ed25519 key and deploy it:

ssh-keygen -t ed25519 -C "you@example.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

If you can't replace the key right now, you can temporarily re-enable the old scheme by adding this line to /etc/ssh/sshd_config and restarting sshd:

PubkeyAcceptedAlgorithms +ssh-rsa

Don't leave that in place permanently — SHA-1 is cryptographically broken. This directive was called PubkeyAcceptedKeyTypes in OpenSSH 8.4 and earlier; both names still work, but PubkeyAcceptedAlgorithms is the current one. See the OpenSSH legacy options page for the full picture on deprecated algorithms.

Fix 5: connecting as the wrong user

SSH key auth is per-user — your key lives in a specific user's ~/.ssh/authorized_keys. Connect as the wrong username and the server looks in the wrong home directory, finds nothing, and refuses access. This is surprisingly common with cloud instances, where the default login user varies by AMI.

Platform / image Default SSH user
Ubuntu (AWS, Azure, GCP)ubuntu
Amazon Linux 2 / 2023ec2-user
RHEL / CentOS (AWS)ec2-user or centos
Debian (AWS)admin
CoreOS / Flatcarcore
Generic Linux VPSroot, or set at provisioning time

A quick diagnostic: try ssh root@server -v — some distros redirect with a message like "Please login as the user 'ubuntu' rather than 'root'." Otherwise, check your cloud provider's documentation for the AMI you launched.

Fix 6: SELinux blocking authorized_keys (RHEL, CentOS, Fedora)

On SELinux-enforcing systems, sshd may be prevented from reading authorized_keys even when the Unix permissions are exactly right. This usually happens when ~/.ssh was created manually or files were copied in from a path with a non-standard security context.

Check the audit log for the specific denial:

sudo grep sshd /var/log/audit/audit.log | grep denied

If SELinux is the cause, restoring the default file context usually fixes it:

restorecon -Rv ~/.ssh

If the user's home directory is in a non-standard location and restorecon applies the wrong label, set the context explicitly:

chcon -R -t ssh_home_t ~/.ssh

SSH file permission reference

Path Required permissions Notes
~ (home directory)755 or more restrictiveMust not be group- or world-writable
~/.ssh/700Owner only
~/.ssh/authorized_keys600Owner read/write only
~/.ssh/id_ed25519 (private key)600Never set wider than this
~/.ssh/id_ed25519.pub (public key)644World-readable is fine — it's public data

Frequently asked questions about SSH permission denied (publickey)

Why does ssh-copy-id keep prompting for a password?

That's expected. ssh-copy-id uses password authentication to log in once and install your public key — so password login needs to be working for that step. After the key is in place, you can set PasswordAuthentication no in sshd_config if you want keys-only access going forward.

Permissions look right but the key still doesn't work — what am I missing?

Check the home directory first: ls -ld ~. Group-writable home directories are the thing most people overlook. After that, check ownership — ls -la ~/.ssh should show your username as owner, not root or another user. On RHEL/CentOS, run restorecon -Rv ~/.ssh. Finally, confirm what path AuthorizedKeysFile in sshd_config is actually pointing to.

Can I have multiple public keys in authorized_keys?

Yes — one key per line, no separator needed. ssh-copy-id appends without overwriting. If you're revoking access, just delete the corresponding line.

Do I need to restart sshd after changing sshd_config?

Yes. Run sudo sshd -t first to check for syntax errors, then restart: sudo systemctl restart ssh on Ubuntu/Debian, sudo systemctl restart sshd on RHEL/CentOS/Fedora. Always test the change from a second terminal before closing your current session — if the config is broken, you'll still have a way back in.

The same key works from one machine but fails from another — why?

The private key only lives on the machine it was generated on. On a new workstation, you don't have the private key that matches the public key the server is expecting. Generate a new pair on the new machine with ssh-keygen -t ed25519 and add its public key to the server's authorized_keys with ssh-copy-id.

What's the difference between ssh -v, -vv, and -vvv?

Each extra v increases verbosity. For key auth failures, -vvv is worth the noise — it shows which keys were offered, whether the server accepted them at the algorithm level, and exactly where the process stopped. Use -v for quick checks and -vvv when you're stuck.