Join our Newsletter — 33% off our NHI Course
Home› Guides› SSH Permission Denied (publickey) Troubleshooting Guide
Guide Authentication

SSH Permission Denied (publickey) Troubleshooting Guide

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 15 min read
On this page

"Permission denied (publickey)." is the one line OpenSSH prints when the server has refused every key the client offered, and it says nothing about why. The real reason is almost always in one of three places: the client's verbose output, the server's authentication log, or the file permissions on the server account. This guide walks through each symptom, ranks the likely causes from most to least common, shows where to look to confirm each one, and gives the fix and the prevention. It is for Linux administrators, platform engineers and anyone who owns SSH access for people, CI runners and automation accounts. Key lifecycle and server hardening are covered in the SSH Key Management Guide and the OpenSSH Server Hardening Guide, which this page does not repeat. Behaviour was checked against the OpenSSH manual pages and source on 11 November 2026.

Key takeaways

  • The client message is generic by design. The server does not tell an unauthenticated client why a key failed, so diagnose from ssh -vvv on the client and the sshd log on the server, never from the error line alone.
  • Most failures are mundane. Wrong user name, the wrong key offered, a key not loaded in the agent, or a public key missing from authorized_keys account for the large majority of cases.
  • StrictModes is the silent killer. sshd ignores authorized_keys if the file, ~/.ssh or any parent directory up to the home directory is group- or world-writable, or owned by another user, and it logs "bad ownership or modes" only on the server.
  • Algorithm drift breaks old keys. Since OpenSSH 8.8 (released 26 September 2021) RSA signatures using SHA-1 are disabled by default, so very old clients or servers can fail with a valid key.
  • Never fix it by weakening the server. Turning off StrictModes, enabling password authentication or re-adding ssh-rsa globally converts an access fault into a security exposure. Fix the account, the key or the client.

What the error actually means

During public key authentication the client offers each candidate public key in turn. For each one the server checks whether the key is authorised for the requested account (via AuthorizedKeysFile, AuthorizedKeysCommand or a trusted certificate authority) and whether its algorithm is accepted. If the key is acceptable, the client proves possession by signing. When the list of offered keys is exhausted and the server's remaining methods are only publickey, the client prints Permission denied (publickey). The text in brackets is the list of methods the server still allows, so (publickey,password) or (publickey,keyboard-interactive) tells you the server would also accept other methods.

Three facts shape the diagnosis:

  • Which keys were offered: only the client knows. Verbose output shows each identity file it found, each key it offered and the server's answer.
  • Why a key was refused: only the server knows. sshd writes the reason to its log, at the default LogLevel INFO for permission problems and at VERBOSE or DEBUG for more detail.
  • Whether the account can log in at all: controlled by AllowUsers, DenyUsers, AllowGroups, account locks and the login shell, independent of the key.

Triage in five minutes

  1. Run the client verbosely. ssh -vvv user@host (the manual allows up to three -v options). For a specific key add -i ~/.ssh/keyfile, and add -o IdentitiesOnly=yes so the agent does not offer other keys first.
  2. Read the identity lines. Lines such as identity file /home/u/.ssh/id_ed25519 type -1 mean the file was not found. GitHub's documentation notes that -1 means SSH could not find a file to use. A key that is found shows a non-negative type and an "Offering public key" line.
  3. Read the server reply to each offer. "Server accepts key" followed by a failure points to the private key or agent (signing failed). No acceptance means the server did not find the key authorised for that account.
  4. Confirm the user name. Look for "Authenticating to host:22 as 'user'". A wrong account is the single most common cause.
  5. Check the agent. ssh-add -l -E sha256 lists loaded key fingerprints. Compare them with the fingerprint of the key in authorized_keys (ssh-keygen -lf on the public key).
  6. Read the server log. On systemd hosts journalctl -u ssh or journalctl -u sshd (the unit name varies by distribution), otherwise /var/log/auth.log (Debian, Ubuntu) or /var/log/secure (RHEL family).

Symptom and cause reference

Causes are listed from most to least common in typical estates. Server log messages are quoted from the OpenSSH portable source (auth.c, misc.c, auth2-pubkey.c); exact prefixes vary with version and syslog format.

Likely causeWhere it showsEvidenceFix
1. Wrong remote userClient -v; server log"Authenticating to ... as 'x'"; server logs Invalid user x from ... for unknown accountsUse the right account (for Git hosting this is git; on cloud images the image's default user)
2. Wrong or no key offeredClient -vtype -1 on identity lines; the needed fingerprint never appears in "Offering"-i plus IdentitiesOnly yes, or an IdentityFile entry in ~/.ssh/config
3. Public key not authorisedServerKey absent from the account's authorized_keys, wrapped across lines, or carrying a from= option that excludes the clientAdd the single-line public key; verify with ssh-keygen -lf
4. Too many keys in the agentClient -v; server logDisconnect with "Too many authentication failures"; server logs "maximum authentication attempts exceeded" (MaxAuthTries defaults to 6)IdentitiesOnly yes per host; fewer agent keys
5. StrictModes rejectionServer log onlyAuthentication refused: bad ownership or modes for directory /home/u/.ssh (or for file)Correct owner and remove group/other write on home, ~/.ssh and authorized_keys
6. Client ignores private keyClientWARNING: UNPROTECTED PRIVATE KEY FILE! and "bad permissions: ignore key"chmod 600 (or 400) on the private key; owner-only ACL on Windows
7. Account not allowedServer logUser u from h not allowed because not listed in AllowUsers, "not in any group", "account is locked" or a shell problemAdjust AllowUsers/AllowGroups through change control, unlock or fix the shell
8. Algorithm not acceptedClient -vvv; server logKey offered but skipped; server mentions PubkeyAcceptedAlgorithmsMove to Ed25519 or ECDSA; a scoped +ssh-rsa only as a temporary per-host exception
9. Wrong AuthorizedKeysFile or commandServer config and logFile path differs from the default .ssh/authorized_keys .ssh/authorized_keys2; AuthorizedKeysCommand errors or times outRun sshd -T to print effective config; test the command as its configured user
10. Certificate problemsServer logExpired certificate, principal not in AuthorizedPrincipalsFile, CA not in TrustedUserCAKeysReissue with correct principals and validity; see the SSH Protocol and Certificate Authority Guide
11. Mandatory access controlAudit logSELinux denial on a relocated or restored .ssh directory with a wrong labelRestore the default file context instead of disabling enforcement

Diagnosing the client side

Which key is actually offered

The ssh manual lists the default identity files: ~/.ssh/id_rsa, id_ecdsa, id_ecdsa_sk, id_ed25519, id_ed25519_sk and, in current releases, id_mldsa44_ed25519. A key with any other name is never tried unless you pass -i, set IdentityFile, or load it into the agent. When an agent is running, its keys are offered first, which is how a laptop with eight keys hits MaxAuthTries before reaching the right one.

  • Pin the key per host: a Host block with IdentityFile and IdentitiesOnly yes is the durable fix for multi-key users and for Git hosting accounts with several identities.
  • Jump hosts: with agent forwarding the forwarded keys are offered, not files on the jump host; prefer ProxyJump.
  • Elevated shells: GitHub warns against running Git with sudo, because root's ~/.ssh and agent are different from the user's, so the key you generated is not the one offered.

Private key permissions on the client

The ssh manual states that ssh will ignore a private key file if it is accessible by others. AWS documents the resulting warning block, ending in "This private key will be ignored." and then the permission denied line. On Linux and macOS set the key to 600 or 400. On Windows, AWS documents resetting the ACL with icacls so that only the current user has read access and inheritance is removed.

Diagnosing the server side

Read the effective configuration

Run sshd -T (as root) to print the configuration sshd will actually use, including defaults and included files. Add -C user=alice,host=client.example,addr=203.0.113.10 to evaluate Match blocks for a specific connection, because a Match block can override AuthorizedKeysFile, PubkeyAuthentication or AuthenticationMethods for some users only. Run sshd -t after every edit to validate syntax before reload.

StrictModes and ownership

StrictModes defaults to yes. In the OpenSSH source the check rejects the key file if it is not a regular file, is owned by someone other than the user (or root), or is writable by group or others (mode bits 022), and then walks every parent directory up to the home directory applying the same owner and write test. That means:

  • Typical triggers: a home directory created as 775 by a provisioning script, a .ssh directory copied by root and left root-owned, or a shared group-writable home on NFS.
  • Safe settings: home directory without group or other write, ~/.ssh at 700, authorized_keys at 600, all owned by the account. These are stricter than the minimum the code enforces and match the ssh manual's recommendations and the AWS recovery steps.
  • Wrong fix: setting StrictModes no lets any user who can write to another user's directory plant a key.

Raise log detail temporarily

sshd supports LogLevel values from QUIET to DEBUG3, default INFO. VERBOSE logs the fingerprint of each key used to log in and is a reasonable permanent setting for audit. Use DEBUG levels only briefly: they can record sensitive detail. A safer alternative is a one-off debug instance on a spare port (sshd -d -p 2222), closed afterwards.

Account and policy gates

The source logs explicit reasons when an account is blocked before keys are considered, for example "not allowed because not listed in AllowUsers", "not in any group" and "account is locked". Check passwd -S or chage -l for locks and expiry, and confirm the login shell exists and is listed in /etc/shells. If AuthenticationMethods requires publickey,keyboard-interactive or similar, a valid key is only the first step and the second factor must also succeed.

Key types, algorithms and version drift

SituationBehaviourRecommended action
RSA key, modern client and serverSigns with rsa-sha2-256 or rsa-sha2-512; worksPlan migration to Ed25519 at next rotation
Modern client (8.8 or later) to a legacy server that only supports ssh-rsaRSA/SHA-1 signatures disabled by default; authentication or host key negotiation failsUpgrade the server; a per-host PubkeyAcceptedAlgorithms +ssh-rsa in ~/.ssh/config only as a time-boxed exception, as the 8.8 release notes advise
DSA keyNot offered or not accepted by current OpenSSHReplace with Ed25519
Ed25519 on FIPS-constrained hostsGitLab notes Ed25519 may fail on some FIPS systemsUse ECDSA P-256 or RSA per the host's approved algorithms

If the organisation has narrowed PubkeyAcceptedAlgorithms for compliance, keys outside the list fail despite a valid authorized_keys entry: compare the offered key type with sshd -T | grep pubkeyacceptedalgorithms.

Automation, CI and Git hosting

Machine use of SSH fails in different ways from human use, and the fixes carry more risk because they are scripted.

  • CI runners: the key is usually injected from a secret store into a file or agent at job start. Check that the file is written with 600 permissions, has a trailing newline, and that IdentitiesOnly yes is set. A key pasted with Windows line endings or a missing final line fails as "invalid format" or is silently skipped.
  • Deploy keys: Git hosts typically allow one repository per deploy key. Using the same key for a second repository is refused. Audit these regularly; see How to find unused GitHub deploy keys and SSH keys.
  • Git user: GitHub documents that connecting as your GitHub user name rather than git returns permission denied. Successful ssh -T [email protected] returns a greeting with the account name, which also tells you which account the key belongs to.
  • Cloud images: AWS documents per-image default users such as ec2-user, ubuntu, admin (Debian) and rocky, and that the instance's key pair name must match the key you hold. Prefer the provider's identity-based access (such as short-lived keys pushed per session) to sharing a launch key.
  • Service accounts: automation accounts with authorized_keys entries are non-human identities. Add a from= restriction and, where possible, a forced command=, and record an owner for each key. See the SSH Key Management Guide.

Fixing safely: an ordered approach

  1. Keep a session open. Before changing sshd_config or permissions on a remote host, keep an existing root or console session so a mistake does not lock you out.
  2. Fix the client first. User name, -i, IdentitiesOnly, agent contents and private key permissions need no server change.
  3. Fix the account second. Correct ownership and modes, add the public key on a single line, confirm fingerprint match.
  4. Change server configuration last. Edit, run sshd -t, reload (not restart) the service, and test with a new connection while the old session stays open.
  5. Roll back cleanly. Keep the prior sshd_config as a dated backup; if the new connection fails, restore it, validate and reload.
  6. Remove temporary exceptions. Debug instances, raised log levels and per-host algorithm overrides get an expiry date in the ticket.

If access is lost entirely on a cloud VM, use the provider's serial console or documented offline volume recovery rather than opening password authentication to the internet.

Detection and measurement

Permission denied events are also the background noise of brute force and key-spraying. Distinguish the two.

  • What to log: sshd at LogLevel VERBOSE so accepted and failed public key events include key fingerprints; forward to the SIEM with host, user, source address and fingerprint fields parsed.
  • Signals of attack: many Invalid user lines from one source, failures across many hosts for the same fingerprint, or "Too many authentication failures" from addresses outside your estate (ATT&CK T1110 Brute Force).
  • Signals of persistence: a new, unexplained line in authorized_keys on a host or service account (ATT&CK T1098.004 SSH Authorized Keys). The Cursor marketplace extension compromise is a recent example of an attacker planting their own SSH key through a tampered developer tool.
MetricWhy it mattersTarget direction
Share of tickets resolved by weakening config (StrictModes off, passwords on)Measures unsafe fixesZero
Hosts with authorized_keys entries without a recorded ownerUnowned keys cannot be safely removed or fixedDown
Keys using RSA/SHA-1 only or DSAPredicts version-drift outagesZero
Hosts logging at VERBOSE with fingerprints in the SIEMCoverage for both diagnosis and detectionUp to 100%

Common failure patterns

  • Disabling StrictModes to "make it work": fixes the symptom and lets any writer of the directory add keys.
  • Re-enabling passwords during an incident: the outage ends and an internet-facing password login begins. Use console access instead.
  • Global +ssh-rsa: a server-wide algorithm exception added for one legacy client and never removed.
  • Copying keys between hosts with root: leaves .ssh root-owned and fails StrictModes on every host it touched.
  • Shared launch keys: one cloud key pair used by a whole team, so "permission denied" after a rotation hits everyone and the fix is to distribute the private key again. The GitHub RSA SSH host key exposure shows how much work a single exposed private key creates.

Framework mapping

FrameworkReferenceRelevance
NIST CSF 2.0PR.AA-01, PR.AA-03, PR.PS-04Credential management, authentication of users and services, log generation
NIST SP 800-53 Rev. 5IA-2, IA-5, AC-6, AC-7, AU-2Authentication, authenticator management, least privilege, failed logon handling, event logging
CIS Controls v8.15 Account Management, 6 Access Control Management, 8 Audit Log ManagementAccount inventory, key-based access, log collection
ISO/IEC 27001:2022 Annex A5.17 Authentication information, 8.5 Secure authentication, 8.15 LoggingKey handling, authentication mechanism, event records
MITRE ATT&CK v20T1021.004 SSH, T1098.004 SSH Authorized Keys, T1552.004 Private Keys, T1110 Brute ForceWhat the same logs reveal when the failures are malicious

Practitioner checklist

  • Always start with ssh -vvv and the server log, not with configuration changes.
  • Confirm the remote user name and the fingerprint of the key actually offered.
  • Pin keys per host with IdentityFile and IdentitiesOnly yes.
  • Keep home without group/other write, ~/.ssh at 700, authorized_keys at 600, all owned by the account.
  • Use sshd -T -C ... to see effective settings, including Match blocks.
  • Validate with sshd -t, reload, and test with a second session before closing the first.
  • Never resolve an access fault by disabling StrictModes or enabling password login.
  • Run sshd at LogLevel VERBOSE and alert on unexpected new authorized_keys entries.
  • Retire DSA and RSA/SHA-1-only keys and time-box any algorithm exception.

Standards and references

Related NHI Mgmt Group resources: SSH Key Management Guide, OpenSSH Server Hardening Guide, SSH Protocol and Certificate Authority Guide, How to Find ssh authorized keys across a server fleet, SSH Key Compromise Response Playbook.

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.