| title | SSH Permission denied (publickey) | |||||
|---|---|---|---|---|---|---|
| slug | linux-ssh-permission-denied-publickey | |||||
| technologies |
|
|||||
| severity | medium | |||||
| tags |
|
|||||
| related |
|
|||||
| last_reviewed | 2026-06-27 |
git@github.com: Permission denied (publickey).
user@host: Permission denied (publickey).
sshd[2210]: Authentication refused: bad ownership or modes for directory /home/deploy/.ssh
sshd[2210]: Connection closed by authenticating user deploy 10.0.0.5 port 51022 [preauth]
Permission denied (publickey) means the SSH server offered public-key
authentication, the client presented one or more keys, and none were accepted
β so the connection is refused. It is an authentication failure, not a network
or connectivity problem (you reached sshd fine). The most common and most
surprising cause is not a missing key at all but wrong file permissions/
ownership on ~/.ssh, authorized_keys, or the private key: sshd silently
rejects keys when the surrounding files are group/world-accessible, and the
client refuses to use a private key with loose permissions.
- linux (OpenSSH client/server, file permissions)
medium β for an interactive user it is an access nuisance, but for automation
(CI deploys, git over SSH, Ansible, backups) it breaks pipelines and scheduled
jobs. A permissions regression after a restore or a bad chmod -R can lock out
every key-based login at once.
- Wrong permissions/ownership on
~/.ssh(must be 700) orauthorized_keys(600) βsshdrejects keys if these are too open. - The public key isn't in the target user's
authorized_keys(or the wrong user/host). - The client isn't offering the right key (no matching
IdentityFile, agent not loaded, or too many keys offered and the server hitsMaxAuthTries). sshd_configdisallows it:PubkeyAuthentication no, restrictiveAllowUsers/AllowGroups, orPermitRootLogin prohibit-passwordfor root.- SELinux/AppArmor context wrong on
authorized_keysafter a manual copy.
On each connection sshd checks the target user's ~/.ssh/authorized_keys, but
first it enforces strict modes: if ~, ~/.ssh, or authorized_keys is
writable by group/other (or owned by the wrong user), it refuses the key and logs
bad ownership or modes β without telling the client why, which is why the
client only sees the generic "Permission denied (publickey)". On the client side,
ssh likewise refuses to load a private key whose file is group/world-readable
("UNPROTECTED PRIVATE KEY FILE"). So the same terse message can originate on
either end; the server's sshd logs and the client's ssh -v trace disambiguate
which key was tried and why it was rejected.
# CLIENT: verbose handshake β which keys are offered and the server's responses
ssh -vvv user@host 2>&1 | grep -iE 'offering|authentications|publickey|denied'
# CLIENT: permissions on key files (private must NOT be group/world readable)
ls -ld ~/.ssh ; ls -l ~/.ssh/id_* ~/.ssh/config
# CLIENT: keys currently loaded in the agent
ssh-add -l
# SERVER: the real rejection reason in the sshd journal
sudo journalctl -u ssh -u sshd --no-pager | grep -iE 'authentication refused|bad ownership|invalid|accepted|denied' | tail -20
# SERVER: target user's ssh dir permissions and the effective sshd config
sudo ls -ld /home/deploy/.ssh ; sudo ls -l /home/deploy/.ssh/authorized_keys
sudo sshd -T 2>/dev/null | grep -iE 'pubkeyauthentication|authorizedkeysfile|allowusers|permitrootlogin'# SERVER journal β the smoking gun
sshd[2210]: Authentication refused: bad ownership or modes for directory /home/deploy/.ssh
# Healthy permissions look like:
drwx------ 2 deploy deploy 4096 .ssh
-rw------- 1 deploy deploy 563 .ssh/authorized_keys
If ~/.ssh is drwxrwxr-x or authorized_keys is -rw-rw-r--, that loose mode
is the cause. On the client, ssh -vvv showing Offering public key ... then
Authentications that can continue: publickey (and looping) means the offered
key wasn't in authorized_keys.
-
Fix permissions/ownership on the server for the target user (most common fix):
sudo chown -R deploy:deploy /home/deploy/.ssh sudo chmod 700 /home/deploy/.ssh sudo chmod 600 /home/deploy/.ssh/authorized_keys
-
Ensure the correct public key is present:
cat ~/.ssh/id_ed25519.pub(client) appears in the server'sauthorized_keys. Usessh-copy-id user@hostto add it safely. -
On the client, fix private-key perms (
chmod 600 ~/.ssh/id_ed25519) and load it:ssh-add ~/.ssh/id_ed25519, or point at it with-i/IdentityFile. -
If
sshd_configblocks it, enablePubkeyAuthentication yesand adjustAllowUsers/PermitRootLogin, thensudo systemctl reload ssh. Risk: keep an open session while editingsshd_configso a mistake doesn't lock you out. -
If SELinux is enforcing, restore context:
sudo restorecon -Rv /home/deploy/.ssh.
ssh -o BatchMode=yes user@host 'echo SSH_OK' # expect: SSH_OK, no password prompt
# Server side, confirm a clean accept:
sudo journalctl -u ssh | grep -i 'Accepted publickey' | tail -1- Never
chmod -R 777a home directory; manage.sshperms explicitly. - Provision keys via configuration management with correct ownership/modes.
- Edit
sshd_configonly with a second open session andsshd -tvalidation. - Use
ssh-copy-idrather than hand-editingauthorized_keys. - Run
restoreconafter restoring/copying.sshon SELinux systems.
linux Β· ssh Β· authentication Β· permissions Β· production