Fix "Permission denied (publickey)" in SSH

Quick fix

Run the connection verbosely to see which user and key are being tried, then make sure that exact public key is in the remote user's ~/.ssh/authorized_keys with strict permissions.

ssh -v user@server 2>&1 | grep -Ei 'offering|authenticat|identity'
# if you still have any way in (password, console), copy the key:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# on the server, fix permissions:
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

The full message usually looks like one of these:

[email protected]: Permission denied (publickey).
alice@server: Permission denied (publickey,password).
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

What the error means

The TCP connection worked and the SSH server answered, so this is not a network problem. The server then tried every authentication method it allows (listed in the parentheses) and none succeeded. publickey alone means the server accepts only keys, so either your client offered no key, offered the wrong one, or the server could not match it to the account you asked for.

The quickest way to narrow it down is the client debug output:

ssh -v alice@server

Example output:

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

"Offering public key" followed by another "Authentications that can continue" means the server saw the key and rejected it: the fault is on the server side (authorized_keys or permissions). No "Offering" line at all means your client never sent a key: the fault is on your side.

Cause 1: wrong user name

Keys are installed per account. Connecting as root or your local user when the key sits in another account always fails. Cloud images use fixed default users: ubuntu on Ubuntu, admin on Debian images, fedora on Fedora Cloud, ec2-user on Amazon Linux, arch on Arch cloud images. For Git hosting the user is always git.

ssh [email protected]
ssh -T [email protected]

Also note that many servers set PermitRootLogin prohibit-password or no, so root login can be refused even with a correct key.

Cause 2: your client is not offering the right key

SSH tries default key files (~/.ssh/id_ed25519, ~/.ssh/id_ecdsa, ~/.ssh/id_rsa) and whatever is in the agent. A key with a custom name is not tried unless you point to it.

# use a specific key once
ssh -i ~/.ssh/work_key alice@server
# load it into the agent
ssh-add ~/.ssh/work_key
ssh-add -l

Make it permanent in ~/.ssh/config:

Host myserver
    HostName 203.0.113.10
    User alice
    IdentityFile ~/.ssh/work_key
    IdentitiesOnly yes

IdentitiesOnly yes stops the agent from offering a long list of other keys first; servers stop after MaxAuthTries (6 by default), and a crowded agent can use up all attempts before the right key is tried. Your private key file must also be private (chmod 600 ~/.ssh/work_key) or ssh refuses to use it with "UNPROTECTED PRIVATE KEY FILE". See setting up SSH keys for creating and managing keys.

Cause 3: the public key is not in authorized_keys

The server compares your key against ~/.ssh/authorized_keys of the target user. If you can log in any other way (console, password, another admin), add the public key (.pub):

# from your machine, if password login still works
ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@server
# or manually on the server, as alice
mkdir -p ~/.ssh
echo 'ssh-ed25519 AAAAC3Nza... alice@laptop' >> ~/.ssh/authorized_keys

Each key must be on one line. Copy-pasting through some terminals and editors inserts line breaks, which silently breaks the entry. Compare fingerprints on both sides:

# on the client
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# on the server
ssh-keygen -lf ~/.ssh/authorized_keys

For GitHub, GitLab or similar, the key goes in your account settings instead; check it by fingerprint there.

Cause 4: permissions or ownership on the server

With StrictModes yes (the default), sshd ignores authorized_keys if the file, ~/.ssh or the home directory can be written by anyone other than the user. This often happens after copying files as root or running a broad chmod.

# run as root on the server, replace alice
chown -R alice:alice /home/alice/.ssh
chmod 700 /home/alice/.ssh
chmod 600 /home/alice/.ssh/authorized_keys
chmod go-w /home/alice

On Fedora, RHEL-family and openSUSE Leap 16 (SELinux enforcing), files created or moved in unusual ways can carry the wrong SELinux label. Restore the default labels instead of disabling SELinux:

restorecon -Rv /home/alice/.ssh

Our file permissions guide explains the octal modes used here.

Cause 5: old RSA key or signature algorithm

OpenSSH 8.8 and later disable the old ssh-rsa signature (RSA with SHA-1). Modern clients sign RSA keys with SHA-2 automatically, but very old servers or appliances may only understand SHA-1, and current servers refuse SHA-1 clients. The debug output then shows no mutual signature supported. The clean fix is a new Ed25519 key:

ssh-keygen -t ed25519 -C "alice@laptop"

Re-enabling ssh-rsa for one legacy host (PubkeyAcceptedAlgorithms +ssh-rsa inside a Host block) works, but limit it to that host and plan to replace the device.

Check the server log

The server records why it rejected the key. With console or another session, watch the log while you retry:

# Ubuntu, Debian, Mint (unit is "ssh")
sudo journalctl -u ssh -f
# Fedora, Arch, openSUSE (unit is "sshd")
sudo journalctl -u sshd -f

Typical lines: Authentication refused: bad ownership or modes for directory /home/alice (cause 4), Invalid user bob (cause 1), or User alice not allowed because not listed in AllowUsers (an AllowUsers/AllowGroups rule in /etc/ssh/sshd_config or a file under /etc/ssh/sshd_config.d/). The journalctl cheat sheet covers more filters. Also check that AuthorizedKeysFile has not been changed to another path.

How to prevent it

  • Keep an existing session open whenever you edit sshd_config or keys, and test a second login before closing it.
  • Use one Host block per server in ~/.ssh/config with User and IdentityFile set, so the right pair is always used.
  • Install keys with ssh-copy-id, which sets correct permissions for you.
  • Prefer Ed25519 keys, and keep a second authorized key (or console access) for emergencies.

If the connection does not even reach authentication, you have a different problem: see ssh Connection refused or, for a warning about changed keys, REMOTE HOST IDENTIFICATION HAS CHANGED. The SSH cheat sheet lists the client options used above.

Frequently asked questions

Why does SSH say Permission denied (publickey) when I have a key?

Having a key is not enough: the server must find the matching public key in the target user's ~/.ssh/authorized_keys, and your client must actually offer that key. Run ssh -v to see which keys were offered and rejected.

How do I fix [email protected]: Permission denied (publickey)?

Add your public key (~/.ssh/id_ed25519.pub) to your GitHub account, load the key with ssh-add, and test with ssh -T [email protected]. Always connect as git, not your own user name.

What permissions should ~/.ssh and authorized_keys have?

~/.ssh should be 700 and authorized_keys 600, both owned by the user. The home directory must not be writable by group or others, or sshd ignores the keys.

Can I log in with a password instead?

Only if the server allows it. When the error lists only publickey, password authentication is disabled on the server; you need console access or another admin to add your key.

Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.