Permission denied (publickey)
Three different failures produce this identical message. Reading ssh -v tells you which one you have in about ten seconds.
The short version. The server refused every key you offered
— or you offered none. On a Mac the two most likely reasons are an empty
ssh-agent and an agent holding too many keys, because the
server stops accepting attempts after six. File permissions, which most guides
put first, are a Linux-shaped answer that is rarely the cause on a single-user
Mac.
What is the server actually telling you?
The message means the authentication phase ended with public key authentication as the only method left, and none of the keys presented were accepted. It is not a message about your password, because no password was attempted. It is not a message about the network, because you reached the server and got far enough to be rejected by it. Crucially, it does not distinguish between three quite different situations: your client offered a key and the server did not recognise it, your client offered several keys and ran out of attempts, or your client offered nothing at all because it could not find a key to use. Those three have different fixes, and the error text is identical for all of them. Establishing which one you are in is the whole job.
Start here: what did the client actually offer?
ssh -v you@server.example.com
Run that and read the lines near the end. The verbose transcript names every identity the client tried and where it came from, which answers the question the error message refuses to. These are the lines that matter and what each one tells you:
Line in ssh -v output | What it means |
|---|---|
Will attempt key: ... (agent) |
The key came from ssh-agent. Good — the agent is reachable and
populated. |
Will attempt key: ... explicit |
The key came from an IdentityFile line or -i, read
from disk. |
Offering public key: ... |
The client sent that key's public half to the server for consideration. |
Server accepts key: ... |
The server recognises this key. If authentication still fails after this line, the problem is server-side, not your key. |
Authentications that can continue: publickey |
The server will only accept keys — password authentication is off. Asking for a password will not help. |
No Offering lines at all |
The client had nothing to offer. Jump to the agent section below. |
Cause one: the agent is empty
If ssh -v shows no Offering public key lines, your
client never presented anything and the server's refusal is a formality. Check
what the agent holds with ssh-add -l; when it prints "The agent has
no identities", that is your answer. This happens constantly on macOS after a
restart, because the two configuration options that would repopulate the agent
automatically — UseKeychain and AddKeysToAgent — both
ship set to no. Loading the key once with ssh-add
fixes the session in front of you. Setting those two options fixes it
permanently, which is covered in detail on
ssh-agent and the macOS
Keychain.
ssh-add -l
ssh-add ~/.ssh/id_ed25519
Cause two: the agent holds too many keys
The attempt limit is genuinely counter-intuitive, and it is why "it works on my
colleague's Mac" happens. OpenSSH offers the server every identity it knows
about, one at a time, in order. The server counts those as authentication
attempts, and sshd_config(5) states that
MaxAuthTries "specifies the maximum number of authentication
attempts permitted per connection" with a documented default of
6. If your agent holds seven keys and the right one is eighth
in line, the connection is closed before it is ever tried — and the error you
get is the same "Permission denied (publickey)" as if the key did not exist.
Accumulating keys is normal after a few years of work, so this failure arrives
gradually and looks like the server changed something.
The fix is to stop offering keys indiscriminately. Tell the client to use one specific key for that host and to ignore everything else:
Host server.example.com
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
IdentitiesOnly yes is the important half. Without it, the
IdentityFile line adds a key to the list rather than replacing the
list, and the agent's other keys are still offered first. With it, exactly one
key is presented and the attempt count never gets near the limit. You can
confirm the change worked by counting the Offering lines in
ssh -v — there should now be one.
Cause three: the server does not have your key
If the client offers a key and the server simply does not accept it, then
the public half is not in that account's authorized_keys, or is
not the one you think it is. Compare fingerprints rather than eyeballing the
files: ssh-keygen -l -f ~/.ssh/id_ed25519.pub prints the
fingerprint of your key, and the same fingerprint should appear in the server's
authentication log when you attempt to connect. Copying the key across is what
ssh-copy-id is for, and doing it by hand is where most of the
damage happens — a public key must be one unbroken line, and an editor that
wraps it produces a file that looks correct and never works.
Server-side permissions, when you control the server
OpenSSH refuses to read authorized_keys if the file or the
directories above it are writable by anyone other than the owner, and it fails
silently from the client's point of view. On the server, the home directory
should not be group-writable, ~/.ssh should be 700,
and ~/.ssh/authorized_keys should be 600. The
server's log is the only place this is visible, which is why this cause is so
often missed by people debugging from the client side alone.
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Cause four: local file permissions
Fixing local permissions is the fix every search result leads with, and it is worth doing even though it is rarely the cause on a Mac you have used normally. It becomes the cause after specific events: restoring a home directory from a backup, copying keys from another machine over a network share, or cloning a dotfiles repository that did not preserve modes. When it applies, OpenSSH says so explicitly with a message about permissions being too open, rather than leaving you with a bare "Permission denied" — so if you have not seen that message, this is probably not your problem.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
Cause five: an old server and an RSA key
If the account and the key are both correct and the server is old, the
rejection may be about the signature algorithm rather than the key. OpenSSH 8.8
disabled RSA signatures using SHA-1 by default in September 2021, and a server
that only supports that algorithm will refuse an RSA key your client considers
perfectly good. The give-away is in ssh -v: the key is offered and
declined without the server ever accepting it, on a machine that has not been
updated in years. Ed25519 or RSA in
2026 covers the narrowly scoped way to re-enable it for that one host,
and why doing it globally is a bad trade.
Work through it in this order
- Run
ssh -vand find theOfferinglines. - No offers at all — check
ssh-add -l, load the key, then fix the defaults permanently. - Many offers and an abrupt end — set
IdentitiesOnly yeswith oneIdentityFile. - One offer, declined — compare fingerprints against the server's
authorized_keys. - Server under your control — check permissions on the home directory,
.sshandauthorized_keys. - Old server, RSA key — the signature algorithm, not the key.
Disclosure. This site is published by OnePasswordManager Ltd, developers of SSHMount, a paid macOS app. Every step above uses software that already ships with macOS, and none of it needs our product. That is the point: if this page resolved your problem and you never hear from us again, the page did its job. About this site.
Sources
Every technical claim above is checked against one of these. Where a manual page is quoted, it is the copy shipped by the vendor named, not a third-party summary of it.
- sshd_config(5), the manual page shipped with macOS — MaxAuthTries, default 6 — https://keith.github.io/xcode-man-pages/sshd_config.5.html
- ssh_config(5), the manual page shipped with macOS — IdentitiesOnly, IdentityFile — https://keith.github.io/xcode-man-pages/ssh_config.5.html
- OpenSSH 8.8 release notes — RSA/SHA-1 signatures disabled by default — https://www.openssh.com/txt/release-8.8