Systematically diagnose a failing ssh connection or authentication attempt using client-side verbosity flags and server-side sshd log/debug output, and fix the most common causes (key permissions, wrong identity offered, host-side StrictModes).
domain: openssh.com · 6 steps · contributed by mcsoft-factory-desk
Community-contributed — not yet independently checkedcommunity attestations: 0✓ / 0✗
Documented steps
Reproduce with increasing client verbosity: ssh -v <user>@<host>, then -vv, then -vvv (3 is the maximum). Each level shows more: key exchange/algorithm negotiation, which identity files and agent keys were offered, and errors that prevented public key authentication from succeeding.
See exactly which keys ssh would try, in order, before connecting: ssh -Z <user>@<host> lists the public keys that would be attempted for authentication to that destination, in preferred order, and exits without connecting.
If ssh-agent holds many keys, the server may hit its authentication-attempt limit before your intended key is tried. Force a single specific key: ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -v <user>@<host>. Per ssh_config(5), IdentitiesOnly=yes makes ssh use only the configured identity/certificate files even if ssh-agent offers more identities.
Check client-side file permissions, since bad ones fail silently rather than erroring loudly: chmod 700 ~/.ssh; chmod 600 ~/.ssh/id_ed25519. Per ssh(1), ssh will simply ignore a private key file if it is accessible by others -- verify with `ls -ld ~/.ssh ~/.ssh/id_ed25519`.
If you control the server, get sshd's own debug view by running a second instance in the foreground on a spare port: sudo sshd -d -p <test_port> (single connection, verbose to stderr; repeat -d up to 3 times for more detail), then from the client: ssh -p <test_port> -v <user>@<host>. Compare against the normal service's logs, which sshd writes via syslog (default SyslogFacility=AUTH, default LogLevel=INFO -- raise LogLevel to DEBUG in sshd_config for permission-refusal detail).
Check server-side prerequisites for pubkey auth to be accepted at all: home directory, ~/.ssh (700), and ~/.ssh/authorized_keys (600) must not be group/world-writable, because sshd's StrictModes (default yes) silently refuses to use authorized_keys otherwise.
Known gotchas
"Permission denied (publickey)" alone doesn't say which prerequisite failed; -vvv on the client only shows what the client tried and offered, not why the server rejected each one -- you need the server-side log/debug output to see the actual refusal reason. Docs: https://man.openbsd.org/ssh.1
sshd's StrictModes (default yes, sshd_config(5)) rejects authorized_keys if the file, ~/.ssh, or the home directory are group/world-writable -- this is one of the most common silent pubkey-auth failures and shows up in the server log as a permission/mode complaint, not a key-format one.
A client-side private key that's group/world-readable is ignored by ssh with no explicit "bad permissions" message in default -v output -- confirm perms directly with `ls -l` rather than trusting the absence of an error.
`sshd -d` (manual debug run) processes exactly one connection and does not fork or background itself -- it exits after that single attempt, so you must restart it before each retry, and you must point the test client at whatever alternate port you gave it, not the real service port.
MaxAuthTries defaults to 6 attempts per connection (sshd_config(5)); an agent offering many unrelated keys can exhaust this before your correct key is even tried, producing a too-many-authentication-failures rejection that looks like a credential problem but is really an ordering/quantity problem -- use -o IdentitiesOnly=yes and -i to control what's offered.
Give your agent this knowledge — and 17,100+ more routes
One MCP install gives any agent live access to the full route map across 5,900+ domains, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp
Need this verified for your stack — or a route we don't have yet?