← Back to Blog

SSH Permission Denied (publickey): The Complete Fix for Every Scenario

You are trying to SSH into a server. You type the command, hit enter, and get slapped with Permission denied (publickey). No helpful explanation. No hint about what went wrong. Just a dead stop. This guide will walk you through every possible cause and fix, from the most common to the most obscure.

TL;DR - Check These 3 Things First

  1. Key file permissions: Run chmod 600 ~/.ssh/id_rsa (your private key must not be readable by others)
  2. Correct username: AWS uses ubuntu, ec2-user, or admin depending on the AMI, not root
  3. Key loaded in ssh-agent: Run ssh-add -l to check, then ssh-add ~/.ssh/id_rsa to load it

Still stuck? Run ssh -vvv user@host to see exactly where authentication fails, then read on.

What "Permission denied (publickey)" Actually Means

Let me clear up a misconception first. This error does not mean your password is wrong. It means the server is configured to only accept public key authentication, and the key exchange failed. The server looked at the keys you offered, compared them against its authorized_keys file, and none of them matched.

There are exactly four reasons this happens:

  • The client is not sending the right key
  • The client is sending the right key but the server cannot read its authorized_keys file
  • The server has the right key but file permissions are blocking access
  • The server configuration is explicitly rejecting the connection

Every fix in this guide maps back to one of those four root causes. The trick is figuring out which one applies to you. That starts with verbose mode.

Step 1: Use Verbose Mode to Find the Problem

Before you start changing permissions and editing config files, you need to know what is actually happening during the SSH handshake. Run your SSH command with triple verbosity:

ssh -vvv user@your-server.com

This dumps the entire authentication process to your terminal. Here is what to look for in the output:

# Good - your key is being offered:
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:xxxx

# Bad - no keys being offered at all:
debug1: No more authentication methods to try.

# Bad - key offered but rejected:
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:xxxx
debug2: we sent a publickey packet, wait for reply
debug1: Authentications that can continue: publickey

The verbose output tells you exactly which keys SSH is trying, in what order, and whether the server is accepting or rejecting each one. If you see No more authentication methods to try, it means SSH ran out of keys to offer before the server accepted any of them. If you see your key being offered and then immediately followed by Authentications that can continue, the server is rejecting that specific key.

Read this output carefully. Nine times out of ten, it points directly to the problem.

Step 2: Fix Key File Permissions

This is the number one cause of SSH permission denied errors, and it catches everyone at least once. SSH is extremely paranoid about file permissions, and for good reason. If your private key is readable by other users on the system, SSH refuses to use it. Same goes for your ~/.ssh directory and the authorized_keys file on the server.

Here are the exact permissions SSH expects:

# On the client (your machine):
chmod 700 ~/.ssh              # drwx------
chmod 600 ~/.ssh/id_rsa       # -rw-------  (private key)
chmod 644 ~/.ssh/id_rsa.pub   # -rw-r--r-- (public key)
chmod 644 ~/.ssh/config       # -rw-r--r-- (SSH config)

# On the server:
chmod 700 ~/.ssh              # drwx------
chmod 600 ~/.ssh/authorized_keys  # -rw-------
chmod 755 /home/username      # drwxr-xr-x (home dir, NOT 777)

That last one trips people up. Your home directory must not be writable by group or others. If it is, SSH will silently refuse to read authorized_keys because it considers the file potentially compromised. Run ls -la /home/ on the server to check.

If you are on macOS and downloaded a .pem file from AWS, it probably has the wrong permissions out of the box:

# Fix AWS .pem key permissions:
chmod 600 ~/Downloads/my-key.pem

You will know this is the problem if the verbose output shows: WARNING: UNPROTECTED PRIVATE KEY FILE! followed by Permissions 0644 for '/path/to/key' are too open.

Step 3: Verify the Username

Different operating systems and cloud providers use different default SSH usernames. Using the wrong username is one of the most common mistakes, especially when switching between providers or AMI types. The server has no user by that name, so naturally it has no authorized_keys file either, and authentication fails.

Here is a quick reference:

  • Amazon Linux / Amazon Linux 2: ec2-user
  • Ubuntu: ubuntu
  • Debian: admin
  • CentOS / RHEL: centos or ec2-user
  • SUSE: ec2-user
  • Fedora: fedora
  • Bitnami: bitnami
  • DigitalOcean: root
  • Azure: whatever you set during VM creation (often azureuser)

A dead giveaway in the verbose output is: debug1: No more authentication methods to try. user@host: Permission denied (publickey). with the wrong username right there in the error. Double check it.

Step 4: Make Sure Your Key Is Loaded in ssh-agent

If you are using an SSH key with a passphrase (and you should be), the key needs to be loaded into ssh-agent before SSH can use it. Without the agent, SSH cannot decrypt your private key, and authentication fails silently.

First, check if any keys are loaded:

# List loaded keys:
ssh-add -l

# If you see "The agent has no identities", load your key:
ssh-add ~/.ssh/id_rsa

# If ssh-agent is not running at all:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa

On macOS, you can add the key to your Keychain so it persists across reboots:

# macOS: add key to Keychain
ssh-add --apple-use-keychain ~/.ssh/id_rsa

A common gotcha is having multiple keys loaded. SSH tries them in order, and many servers have a MaxAuthTries limit (usually 6). If you have 10 keys loaded and the right one is at the end of the list, the server disconnects before SSH gets to it. You will see Too many authentication failures in that case. The fix is covered in the Pro Tip section below.

Step 5: Specify the Correct Key File

SSH looks for keys in a default order: id_rsa, id_ecdsa, id_ed25519, and id_dsa. If your key has a custom name (like work_server.pem or deploy_key), SSH will not find it unless you tell it where to look.

Use the -i flag to specify the key file explicitly:

ssh -i ~/.ssh/my_custom_key user@server.com

For a more permanent solution, set up an SSH config file at ~/.ssh/config:

# ~/.ssh/config
Host production
    HostName 10.0.1.50
    User ubuntu
    IdentityFile ~/.ssh/prod_key.pem
    IdentitiesOnly yes

Host staging
    HostName 10.0.2.50
    User ec2-user
    IdentityFile ~/.ssh/staging_key.pem
    IdentitiesOnly yes

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_ed25519
    IdentitiesOnly yes

Now you can just run ssh production or ssh staging instead of typing out the full command with flags every time. Use our SSH Config Generator to build these blocks quickly.

Step 6: Fix Server-Side authorized_keys Issues

So the client side looks fine. Your key has the right permissions, the right username, and it is being offered. But the server is still rejecting it. Time to check the server side.

The authorized_keys file must contain your public key (the .pub file content), be in the correct location, and have the correct format.

# Check the authorized_keys file on the server:
cat ~/.ssh/authorized_keys

# Each line should look like:
ssh-rsa AAAAB3NzaC1yc2EAAAA... user@machine
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... user@machine

Common problems with authorized_keys:

  • Wrong file location: It must be at ~/.ssh/authorized_keys for that specific user. Not in root's home when you are logging in as ubuntu.
  • Line breaks in the key: Each key must be on a single line. If you copied the key from an email or a web page, line breaks may have been inserted. The key should be one continuous line starting with ssh-rsa or ssh-ed25519.
  • Wrong key type: Make sure you pasted the public key (.pub), not the private key. The public key starts with ssh-rsa or ssh-ed25519. The private key starts with -----BEGIN OPENSSH PRIVATE KEY-----.
  • Extra whitespace or invisible characters: Some text editors add trailing whitespace or BOM characters. Use cat -A ~/.ssh/authorized_keys to check for invisible characters.

To add a key properly from your local machine:

# From your local machine (if you have password access):
ssh-copy-id -i ~/.ssh/id_rsa.pub user@server.com

# Or manually (if you have console access on the server):
mkdir -p ~/.ssh
echo "ssh-rsa AAAAB3Nza..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

Step 7: Check sshd_config Restrictions

If everything else looks correct, the SSH daemon configuration on the server might be blocking you. The main config file is usually at /etc/ssh/sshd_config. Here are the directives that matter:

# Check these settings in /etc/ssh/sshd_config:

PubkeyAuthentication yes          # Must be "yes" (default)
AuthorizedKeysFile .ssh/authorized_keys  # Default path
PermitRootLogin prohibit-password  # Or "yes" if you need root SSH
AllowUsers ubuntu deploy           # If set, ONLY these users can SSH in
AllowGroups ssh-users              # If set, user must be in this group

The sneaky ones are AllowUsers and AllowGroups. If either directive exists in sshd_config, it acts as a whitelist. Any user not listed is silently rejected, even if their key is in authorized_keys. The error message does not tell you this. You just get the same generic Permission denied (publickey).

After making changes to sshd_config, you must restart the SSH daemon:

# Restart SSH daemon (keep your current session open!):
sudo systemctl restart sshd

# Or on older systems:
sudo service ssh restart

Important: Always keep your current SSH session open when editing sshd_config. If you make a mistake and lock yourself out, you still have the existing session to fix it. Never close your connection until you have verified that a new connection works.

Also check for drop-in config files that might override the main config:

# Check for override configs:
ls /etc/ssh/sshd_config.d/

# These files are loaded after sshd_config and can override settings

Step 8: SELinux and AppArmor Blocking SSH

This one drives people absolutely crazy because everything looks correct. Permissions are right. The key is in authorized_keys. sshd_config is fine. But SSH still says permission denied. If you are on RHEL, CentOS, Fedora, or Amazon Linux, SELinux might be the culprit.

SELinux has its own set of file labels (security contexts) independent of Unix permissions. If the .ssh directory or authorized_keys file has the wrong SELinux context, SSH cannot read them even though standard permissions allow it.

# Check SELinux status:
getenforce

# If "Enforcing", restore correct contexts:
restorecon -Rv ~/.ssh

# Check the current context:
ls -laZ ~/.ssh/

# The correct context should be:
# ssh_home_t for authorized_keys
# user_home_t for .ssh directory

This commonly happens when you manually create the .ssh directory or copy authorized_keys from another location. The file inherits the context of the source, not the destination. Running restorecon fixes the labels based on the SELinux policy for that path.

On Ubuntu with AppArmor, you will rarely hit this issue with SSH, but check the logs anyway:

# Check for AppArmor denials:
sudo dmesg | grep -i apparmor
sudo journalctl -xe | grep -i apparmor

Pro Tip: Force a Specific Key with IdentitiesOnly

If you manage multiple servers with different keys, this one flag will save you hours of debugging:

ssh -o IdentitiesOnly=yes -i ~/.ssh/specific_key user@host

Here is why this matters. By default, SSH tries every key in your agent plus every default key file. If you have five keys loaded and the server has MaxAuthTries 3, SSH might exhaust the retry limit before it gets to the right key. The IdentitiesOnly=yes option tells SSH to only use the key you specified with -i and ignore everything else.

Add this to your ~/.ssh/config Host blocks to make it permanent (as shown in Step 5 above). This is especially important when connecting to servers that have low MaxAuthTries values or when you work with many different cloud providers.

SSH Authentication Methods Compared

Public key is not the only way to authenticate with SSH. Here is how the different methods stack up:

Method Security Level When to Use
Public Key High Default for all servers. Use ed25519 keys for best security and performance.
Password Low Initial setup only. Disable after adding public keys. Vulnerable to brute force.
Keyboard-Interactive Medium to High Multi-factor authentication (MFA/2FA). Used with PAM modules for TOTP or Duo.
GSSAPI (Kerberos) High Enterprise environments with Active Directory or FreeIPA. Single sign-on.
Certificate-Based Very High Large fleets where managing authorized_keys is impractical. Uses SSH CA.

For most people, public key authentication with ed25519 keys is the right choice. Generate one like this:

ssh-keygen -t ed25519 -C "your_email@example.com"

Platform-Specific Fixes

AWS EC2

AWS is the most common source of this error because the username, key, and security group must all align perfectly.

  • Use the correct username for your AMI type (see Step 3 above)
  • Use the .pem key pair that was assigned when the instance was launched, not a different one
  • Make sure your security group allows inbound SSH (port 22) from your IP address
  • Check the Network ACL on the subnet as well, not just the security group
  • If you lost the key, stop the instance, detach the root volume, attach to another instance, mount it, and edit authorized_keys

For detailed AWS security hardening beyond SSH, see our AWS Security Checklist for Production.

GitHub

When you get Permission denied (publickey) from GitHub, the fix is almost always one of these:

# Test your GitHub SSH connection:
ssh -T git@github.com

# If it fails, check which key GitHub is seeing:
ssh -vvv -T git@github.com

# Add your key to GitHub at:
# Settings > SSH and GPG Keys > New SSH Key

# Make sure you copy the PUBLIC key:
cat ~/.ssh/id_ed25519.pub

Common gotcha: you added the key to one GitHub account but you are trying to push to a repo owned by a different account. GitHub uses the key to identify the user, so the key must be on the account that has access to the repository.

GitLab

Same concept as GitHub. Test with ssh -T git@gitlab.com. One difference: GitLab allows you to set key expiration dates. If your key expired, it will be rejected even though it appears in your profile. Check the key expiration in User Settings > SSH Keys.

DigitalOcean

DigitalOcean droplets default to root as the SSH user. If you added SSH keys during droplet creation, they are automatically placed in /root/.ssh/authorized_keys. If you created the droplet with a password instead, you need to log in with the console first and manually add your key.

Azure

Azure VMs use whatever username you specified during creation (the default suggestion is azureuser). The key is injected at provisioning time. If SSH fails, check the Azure Serial Console in the portal for access without SSH. Also verify that the Network Security Group (NSG) allows inbound port 22.

Common Mistakes That Cause Permission Denied

  1. Confusing passphrase with password: Your key passphrase protects the private key file on your local machine. It is not a server password. If SSH asks for a passphrase, it is decrypting your local key, not authenticating to the server. If it asks for a password, the server is falling back to password auth (which is usually disabled).
  2. Pasting the key with extra newlines: When you copy a public key from a web interface, email, or Slack, line breaks often get inserted. The entire key must be one single line in authorized_keys. No line breaks, no extra spaces at the end.
  3. Using ed25519 on a very old server: Servers running OpenSSH versions older than 6.5 (released January 2014) do not support ed25519 keys. If you are connecting to an ancient server, you may need to fall back to RSA: ssh-keygen -t rsa -b 4096.
  4. Home directory owned by wrong user: If the home directory is owned by root instead of the login user, SSH will not trust the authorized_keys file inside it. Run ls -la /home/ to verify ownership: sudo chown -R username:username /home/username.
  5. Using sudo to create .ssh directory: If you run sudo mkdir ~/.ssh, the directory will be owned by root, not your user. SSH checks ownership, and if the .ssh directory is not owned by the login user, it refuses to read from it. Always create it as the target user or fix ownership afterward.
  6. Firewall or port change: SSH defaults to port 22, but many servers change it for security. If the server uses a non-standard port, you will get a connection timeout, not a permission denied error, but it is worth checking if the server is reachable at all: ssh -p 2222 user@host.

Generate SSH Config Blocks Instantly

Stop typing long SSH commands with flags. Use the SecureBin SSH Config Generator to build proper Host blocks for all your servers in seconds.

Generate SSH Config

Frequently Asked Questions

Why does SSH keep saying Permission denied even after I add my key to authorized_keys?

The most common reason is incorrect file permissions. SSH is extremely strict about this. Your home directory must not be writable by group or others, ~/.ssh must be 700, and authorized_keys must be 644 or 600. Also check that the file is owned by the correct user, not root. Run ls -la ~/.ssh/ to verify, and check /var/log/auth.log on the server for the exact rejection reason.

How do I fix SSH Permission Denied on AWS EC2?

First, make sure you are using the correct username for your AMI. Amazon Linux uses ec2-user, Ubuntu uses ubuntu, Debian uses admin, and CentOS uses centos. Then verify you are using the correct key pair that was assigned when the instance was launched. Run ssh -vvv -i /path/to/key.pem username@ip to see exactly where authentication fails. Also check that your security group allows inbound SSH on port 22 from your IP address.

Can I recover access to a server if I lost my SSH private key?

If you lost your private key and have no other way to log in, you cannot authenticate via SSH. For cloud instances like AWS EC2, you can stop the instance, detach the root volume, attach it to another instance, mount it, edit the authorized_keys file to add a new public key, then reattach and restart. For physical servers, you will need console or out-of-band access (like IPMI or iDRAC) to log in and add a new key.

Check Your Server Exposure

While you are fixing SSH, make sure the rest of your server is not exposed. Run a free security scan to check for open ports, exposed files, and missing security headers.

Run Free Security Scan

The Bottom Line

SSH Permission Denied (publickey) is frustrating because the error message tells you almost nothing about what actually went wrong. But the fix almost always comes down to one of three things: wrong permissions, wrong username, or wrong key. Start with ssh -vvv to see the full handshake, fix the obvious issues first, and work your way through the less common causes only if needed.

Once you have access working, take a few minutes to set up an ~/.ssh/config file with proper Host blocks and IdentitiesOnly yes. You will save yourself from running into this error again every time you switch between servers or cloud providers. Use our SSH Config Generator to build those blocks, and check your overall security posture with the Exposure Checker.

Related tools: SSH Config Generator, Chmod Calculator, Exposure Checker, Port Lookup, DNS Lookup, and 70+ more free tools.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.