Diagnosing SSH Public‑Key Authentication Failures on OpenSSH Servers
A step‑by‑step diagnostic guide for SSH public‑key authentication failures, covering permissions, sshd_config, SELinux/AppArmor, agent loading, and key type issues with rollback notes.
11 Nov 2025, 07:01 UTC

Recognizable Condition
When you try to log in with an SSH key and the server replies Permission denied (publickey), the authentication handshake stopped before a password prompt appeared. This usually means the server rejected the offered public key for one of several configuration or environmental reasons.
Cause/Diagnostic Table
| Observed Symptom | Likely Cause |
|---|---|
| Server log shows "Authentication refused: bad ownership or modes for directory" | Incorrect permissions on ~/.ssh or ~/.ssh/authorized_keys |
| Server log shows "User user not allowed because account is locked" | Account locked or shell set to /usr/sbin/nologin |
| Server log shows "Failed publickey for user from X.X.X.X port XXXX ssh2: RSA SHA256:…" | Key type not accepted by server (e.g., RSA < 2048 bits when restricted) |
| Server log shows "Authentication refused: key is not an authorized key" | Key not present in the file pointed to by AuthorizedKeysFile |
SELinux audit logs show AVC denials for ssh_home_t | SELinux context mismatch on ~/.ssh or authorized_keys |
| Client reports "Agent admitted failure to sign using the key" | Private key encrypted and ssh‑agent not running or key not loaded |
| Client sees "Host key verification failed" | Missing or corrupted entry in ~/.ssh/known_hosts |
Ordered Checks
- Verify client‑side agent and key loading
Run
ssh-add -lon the client. If the list is empty, start the agent (eval "$(ssh-agent -s)") and add the key (ssh-add ~/.ssh/id_rsa).Where to run: client workstation. Permissions: user account. Risk: none.
- Examine server authentication logs
On the server, view the most recent SSH attempts:
sudo journalctl -u sshd | tail -n 20 # or sudo grep sshd /var/log/auth.log | tail -n 20Look for lines containing the username and the phrase "publickey". Note the exact reason given (ownership, key type, etc.).
Where to run: server (root or sudo). Permissions: root. Risk: none.
- Check SSH daemon configuration
Run the extended test mode to see effective settings:
sudo sshd -T | grep -E 'PubkeyAuthentication|AuthorizedKeysFile|PubkeyAcceptedKeyTypes'Ensure
PubkeyAuthentication yesand thatAuthorizedKeysFilepoints to a readable file (default.ssh/authorized_keys). IfPubkeyAcceptedKeyTypesis set, confirm your key type appears in the list.Where to run: server (root). Permissions: root. Risk: reading only.
- Inspect
~/.sshdirectory andauthorized_keysfileAs the target user, execute:
ls -ld ~/.ssh ls -l ~/.ssh/authorized_keysExpected output:
~/.sshmode700(drwx------) owned by the user.authorized_keysmode600(-rw-------) owned by the user.
If the mode is more permissive (e.g., 777 or 644) or ownership is root, key authentication will be ignored.
Where to run: server, as the user whose key you are testing. Permissions: user. Risk: changing permissions incorrectly can lock you out; see rollback below.
- Validate SELinux/AppArmor contexts (if applicable)
On systems with SELinux enabled:
ls -Z ~/.ssh/authorized_keysThe context should be
unconfined_u:object_r:ssh_home_t:s0(or the equivalent defined by policy). If it differs, restore the default:sudo restorecon -Rv ~/.sshFor AppArmor, check the profile in
/etc/apparmor.d/usr.sbin.sshdand ensure it allows read of the user’s.sshdirectory.Where to run: server (root). Permissions: root. Risk: incorrect context changes can silently deny access; keep a backup of current contexts (
sudo semanage fcontext -l > /tmp/fcontext.bak). - Test with increased verbosity
From the client, run:
ssh -vvv user@hostnameWatch the output for lines like "offering public key" and the server’s response. The verbosity shows where the handshake stops and often mirrors the server log reason.
Where to run: client. Permissions: user. Risk: none.
Fixes Tied to Findings
- Incorrect permissions/ownership
Fix:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown $USER:$USER ~/.ssh ~/.ssh/authorized_keysRollback (if you need to revert): store original modes with
stat -c '%a %U:%G' ~/.ssh ~/.ssh/authorized_keysbefore changing, then reapply those values. - sshd_config misconfiguration
If
PubkeyAuthentication no, change toyesand ensureAuthorizedKeysFileis correct. Edit/etc/ssh/sshd_configwith a text editor, then:sudo systemctl reload sshd # or sudo service sshd reloadRollback: copy the original file (
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak) before editing; restore it and reload if login fails. - Key type rejected
Either generate a newer key (
ssh-keygen -t ed25519) or adjustPubkeyAcceptedKeyTypesinsshd_configto include your key type, then reload sshd.Rollback: revert the
PubkeyAcceptedKeyTypesline to its previous value and reload. - SELinux/AppArmor denial
Run
sudo restorecon -Rv ~/.sshto fix SELinux contexts. For AppArmor, edit the profile and runsudo systemctl reload apparmor.Rollback: SELinux contexts can be restored with the backup created earlier (
sudo setfiles -v -F /tmp/fcontext.bak). AppArmor profile rollback is the original file copy. - Agent not running or key not loaded
Start the agent and add the key:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsaRollback: simply stop the agent (
ssh-agent -k) if you wish to undo; no persistent state is changed. - Known hosts mismatch
Remove the offending line (
ssh-keygen -R hostname) or correct the entry, then reconnect.Rollback: you can re‑add the old line manually if needed.
Escalation Criteria
- After applying the appropriate fix, you still see
Permission denied (publickey)and the server log shows no new information. - Multiple users on the same host experience the same failure, suggesting a systemic sshd_config or SELinux policy issue.
- You are unable to reload sshd without losing the ability to log in via console or out‑of‑band management.
In these cases, gather the full sshd -T output, the relevant audit logs (ausearch -m avc -ts recent for SELinux, journalctl -a for AppArmor), and contact your system administration team with the collected data before making further changes.
Limitations and Practical Verification
This guide assumes a standard OpenSSH server (sshd version 7.2 or newer) and that you have sudo or root access to the target host. It does not cover hardware‑based authentication tokens, certificate‑based authentication, or custom AuthorizationPrincipals commands. To verify that a fix worked, repeat the ssh -vvv test and confirm that the server logs show "Accepted publickey for user" followed by the session opening. Additionally, run ls -ld ~/.ssh and ls -l ~/.ssh/authorized_keys to ensure permissions remain correct after any changes.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.