First things first: Check file permissions (30 seconds)
This is the #1 cause of SSH publickey failures. OpenSSH is picky about who owns what. If your ~/.ssh directory or authorized_keys file has wrong permissions, SSH will silently reject your key.
Run these commands on the server (the machine you're trying to SSH into):
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/known_hosts
Also make sure the ~/.ssh directory and everything inside is owned by you, not root:
chown -R $USER:$USER ~/.ssh
What's actually happening here is: OpenSSH checks that only the owner can write to authorized_keys. If anyone else (like a group) can write, OpenSSH assumes the file might be tampered with and refuses to use it. The 700 on the directory prevents other users from listing your keys.
Now try SSH again. If it still fails, move on.
Second step: Check the key is in the right format (5 minutes)
OpenSSH 8.8 and later disabled RSA signatures using SHA-1 by default. If you generated your RSA key before 2021, it's probably using the old format that SSH now rejects.
The fix is to generate a new key with Ed25519 algorithm (faster, more secure, no SHA-1 problems):
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519
Copy the public key to the server:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
If ssh-copy-id isn't available (you're on an older system or Windows), do it manually:
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Then on the server, run the permission fix from step 1 again.
If you must keep using RSA (some old systems don't support Ed25519), you can re-enable SHA-1 in your SSH client config. Add this to ~/.ssh/config:
Host old-server
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
I don't recommend this for security reasons, but it works.
Third step: SSH debug mode (15+ minutes)
Still failing? Time to see what SSH actually says. Run the SSH command with verbose output:
ssh -vvv user@server 2>&1 | grep -E "(debug1|debug2|debug3|permission)"
Look for lines like:
debug1: Authentications that can continue: publickey— SSH is ready to try your keydebug1: Offering public key: /home/you/.ssh/id_ed25519— it's sending the keydebug1: Authentication refused: bad permissions— permissions are wrong (go back to step 1)debug1: send_pubkey_test: no mutual signature algorithm— key type mismatch (go back to step 2)debug1: Host 'server' is known and matches the ED25519 key fingerprint— host key is fine
If you see Authentication refused: bad permissions, check the server's /var/log/auth.log or journalctl -u sshd for more detail. The exact line looks like:
Authentication refused: bad permissions for /home/user/.ssh/authorized_keys
Also check if the SSH server is even accepting publickey authentication at all. On the server, look at /etc/ssh/sshd_config and make sure these lines are present and not commented out:
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
Then restart the SSH daemon:
sudo systemctl restart sshd
If you changed PasswordAuthentication no and you haven't tested your key yet, you might lock yourself out. Real advice: test the key before disabling password auth.
Fourth step: SELinux or AppArmor (rare but real)
If you're on CentOS, RHEL, Fedora, or any system with SELinux enabled, it can block SSH key files even with correct permissions. Check SELinux context on the authorized_keys file:
ls -Z ~/.ssh/authorized_keys
It should show unconfined_u:object_r:ssh_home_t:s0. If it's wrong, fix it:
restorecon -Rv ~/.ssh
On Ubuntu with AppArmor, it's less common but check with sudo aa-status. If SSH is confined, you might see denials in dmesg.
When all else fails: The nuclear option
Delete everything in ~/.ssh on the server and start fresh:
rm -rf ~/.ssh
mkdir ~/.ssh
chmod 700 ~/.ssh
Then copy your public key again using the manual cat command from step 2. This fixes any hidden file corruption or old permissions that regular chmod didn't touch.
The reason this works is: OpenSSH caches nothing. It reads the file fresh each time. A clean directory removes any doubt about file attributes, ACLs, or extended permissions that regular chmod doesn't reset.
Most people never need to go this far. Start with permissions, then key format, then debug output. 9 times out of 10, step 1 or step 2 fixes it.