SSH Permission Denied (publickey): How to Fix It

What does the ssh permission denied publickey error mean, and what should you do first?
The ssh permission denied publickey error means the server accepted none of the keys your client offered. First run ssh -v user@host, check which key the client tried, and confirm that the matching public key is registered on the server or in your GitHub account.
Do not panic, because this error is rarely a crash or a lost server. It is usually a small mismatch between two files. Below we give the diagnosis order we use in the field, from the most likely cause to the least likely, because random guessing only wastes your time.
What is the quick fix for ssh permission denied publickey in the first five minutes?
The list below covers most cases of this error. Retry the connection after each step, and stop as soon as it works. Then you avoid needless changes.
- Check the username and the host. For GitHub the username is always
git. - Connect with
ssh -vand confirm that the right key shows up in the "Offering public key" lines. - Confirm that your public key sits in the server's
authorized_keysfile or in your GitHub account. - Run
ssh-add -lto see whether the agent holds your key, and load it withssh-addif it does not. - Tighten the permissions on the
~/.sshfolder and your key files. - Define an
IdentityFileline in~/.ssh/configif you keep several keys. - For GitHub, test the connection with
ssh -T git@github.com.
We explain each step in its own section below. First, let us see why the error appears at all.
Why does ssh permission denied publickey happen?
Public key authentication uses two parts. You keep the private key on your computer, and you register the public key on the server. The server then sets a challenge that only the matching private key can answer.
The error says that no key passed the challenge. In other words, the server either does not know your key or never saw it. So the problem sits in one of three places. The client offers the wrong key, the server cannot find the right key in its records, or file permissions make the server ignore the record.
Also, if the server has turned off password login, there is no fallback. That is why the word "publickey" in brackets matters. It names the only method the server still accepts.
Are the username and host address correct?
The most common cause is the simplest one. On many Ubuntu images, for example, the default user is ubuntu, while other images use root or admin. If you connect as the wrong user, the server looks in that user's records and finds nothing, even when your key is fine.
- Read the default username in your hosting or cloud panel.
- Write the full
user@hostform, because otherwise the client sends your local username. - If you run several servers, check that the name points to the right machine with our DNS lookup tool.
- If the port is different, set it with
-p. Otherwise you may be talking to another service.
This check takes one minute. However, if you skip it, every later step is wasted effort.
How do you see which key SSH tried with ssh -v?
Verbose mode lets you stop guessing, so you see the facts. The OpenSSH manual says that -v turns on debug output, and each extra -v adds detail. Then start the connection like this:
ssh -v user@example.comThen look for these lines in the output:
- Offering public key: shows which key file the client presents. If your expected file is missing, the client never found that key.
- Authentications that can continue: lists the methods the server accepts. If you only see publickey, password login is off.
- No more authentication methods to try: tells you that every attempt failed.
- Will attempt key: shows the order of loaded keys, so you can spot agent problems here.
This way you separate client problems from server problems quickly. If the client offers no key, the issue is on your computer. If it offers the right key and the server still says no, the issue is on the server side.
Is your public key in the server's authorized_keys file?
The server reads the allowed keys from ~/.ssh/authorized_keys in the user's home directory. According to the OpenSSH manual, each line in that file holds one public key. A line may be missing, half copied, or stored in another user's file.
To check, print the public key on your computer and compare it with the line on the server:
cat ~/.ssh/id_ed25519.pub
cat ~/.ssh/authorized_keys- First, the key must be a single line. If a line break split it while copying, the key is invalid.
- Also, the file must hold only public keys with the .pub form, never the private key.
- Next, make sure you added the key to the home directory of the right user. A key added for root does not help when you log in as someone else.
- Instead, the safest way to add a key is
ssh-copy-id, as long as you still have access.
If you cannot reach the server at all, the console or rescue mode in your hosting or cloud panel can help. Read your provider's official guide first, because recovery steps differ.
Why does ssh permission denied publickey appear on GitHub?
The message is the same on GitHub, but the causes differ a little. In practice, the GitHub Docs troubleshooting page asks you to confirm three things. First, the remote address must use SSH. Second, the username must be git. Third, your public key must sit in your account.
- The remote must use the SSH form. Run
git remote -vto see it. If you use an HTTPS address, your SSH key plays no role at all. - If the address looks like
git@github.com:account/repo.git, the username is right. Typing your own username here causes this very error. - Add the public key in the SSH keys section of your GitHub account settings. Menu names can change, so follow the current path on the official help page.
- If the repository belongs to an organization, review that organization's SSH access rules as well.
- If you already added the key to another account, GitHub will not accept the same key on two accounts. Generate a separate key for each account.
If you want to refresh the basics, see our Git and GitHub guide with essential commands.
Why does ssh-agent not see your key?
If your key has a passphrase, or if it does not use a default file name, the client may not find it on its own. The ssh-agent is a helper that keeps unlocked keys in memory. As a result, you do not type the passphrase on every connection.
First, check which keys the agent holds:
ssh-add -l
ssh-add ~/.ssh/id_ed25519- The first command lists the fingerprints of loaded keys. A reply such as "The agent has no identities" means the agent is empty.
- Then the second command adds the key to the agent. If it asks for a passphrase, type the one you set when you created the key.
- Because of this, if the agent holds too many keys, the server may hit its attempt limit before your right key comes up. In that case you must force one specific key, which we cover in the config section.
- If the agent empties every time you close the terminal, read your operating system's documentation about keychain integration.
You often see this after moving to a new computer. The key file has moved, but the agent still has the empty state of the old session.
Why do ~/.ssh permissions break the connection?
OpenSSH checks file permissions for safety, so loose modes cause silent failures. If other users can read your private key, the client refuses to use it and prints a warning such as "UNPROTECTED PRIVATE KEY FILE". On the server side, if the home directory or the .ssh folder is writable by others, sshd may treat the record as unsafe.
The StrictModes option in the sshd_config manual does exactly this check. These are the values people commonly recommend:
| File or folder | Recommended mode | Meaning |
|---|---|---|
~/.ssh folder | 700 | Only the owner can enter and write |
Private key (id_ed25519) | 600 | Only the owner can read and write |
authorized_keys | 600 | Others cannot write, the owner can read and write |
Public key (.pub) | 644 | Readable is fine, but nobody else can write |
| Home directory | Not writable by others | If group or others can write, sshd may reject the record |
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys ~/.ssh/id_ed25519Then run the same commands on the server, in the home directory of the user you log in as. Also verify the exact values in the OpenSSH manual for your own system.
How do you set IdentityFile in ~/.ssh/config?
If you own several keys, or if your key has a non-default name, you must tell the client which one to use. The ssh_config manual defines the IdentityFile and IdentitiesOnly options for this.
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes- Host: sets which server the rule covers.
- User: also fixes the default username, so you do not type it each time.
- IdentityFile: points to the private key to use.
- IdentitiesOnly yes: offers only the named key and does not send the other keys from the agent.
In practice, this setting saves developers who use several GitHub accounts. For example, you create two keys, one for work and one for personal use, and give each a separate Host name. Then the client never offers the wrong account's key.
How do you test the GitHub connection with ssh -T?
Then you can verify the connection with one command before you try to clone anything. GitHub Docs recommends this command to test an SSH connection:
ssh -T git@github.comIf it works, GitHub replies with a greeting that confirms your identity. On the first connection, ssh asks you to confirm the server fingerprint. Compare it with the values that GitHub Docs publishes, then accept.
If you still see "Permission denied (publickey)", add detail with ssh -vT git@github.com. Check whether the key offered matches the key you added to your account. If the wrong key still goes out, return to the config section.
What changes when password login is off on the server?
Hardened servers usually carry the line PasswordAuthentication no. According to the sshd_config manual, this option turns off password login and leaves only key-based methods. It is the right choice for security. However, it also locks you out when your key does not work.
In that situation, you have three safe options:
- First, use the web console or rescue access in your hosting or cloud panel, then fix the key.
- Second, log in with another administrator account, if you have one, and update
authorized_keys. - Otherwise, contact your provider's support. They guide you through the recovery methods after identity checks.
Never try to get around the rules with someone else's account or with strangers who sell "access recovery". These methods are risky for both security and legal reasons, and they often create a second problem.
How do you avoid locking yourself out of the server?
When you change a key or an sshd setting, the biggest risk is closing the working session and then failing to return. The rule is simple. Do not close the old session before you test the new setup.
- First, keep your current session open.
- Then add the new setting or the new key.
- Open a new terminal window and make a separate connection with the new key.
- Next, if the new connection works, close the old session.
- If it fails, undo the change from the old session.
Also, after you edit the sshd configuration, check the syntax before you restart the service. The sshd manual defines a test mode with the -t flag. Then a typo cannot stop the service from starting.
For the full set of server hardening steps, read our Linux swap and SSH hardening guide. If you are putting a new app live, our guide to deploying Next.js on a VPS uses the same connection logic.
Which SSH key type should you choose?
If you generate a new key, ed25519 is a common and recommended choice today. The OpenSSH documentation lists it as a modern signature algorithm, and GitHub Docs uses ed25519 in its key generation steps. If you need compatibility with old systems, you can use RSA, but check the current key length advice in the official documentation.
ssh-keygen -t ed25519 -C "name@example.com"- The command creates the key pair in the default folder and asks you to set a passphrase.
- Because of this, a passphrase makes the key hard to use alone, even if someone steals your laptop.
- A comment (
-C) such as an email or machine name helps you tell keys apart later. - If a very old server does not know ed25519, think about updating its OpenSSH version first.
Which cause matches which symptom and fix?
The table below summarizes the diagnosis order for ssh permission denied publickey. The most likely cause sits at the top, and the least likely sits at the bottom.
| Cause | Symptom | Fix |
|---|---|---|
| Wrong username | The key is offered but rejected | Use the right user, and git for GitHub |
| Key not registered on the server | The right key goes out, yet it fails | Add the public key to authorized_keys or your GitHub account |
| Wrong key offered | The expected file is missing in ssh -v output | Set IdentityFile and IdentitiesOnly |
| Empty ssh-agent | ssh-add -l shows no identity | Load the key with ssh-add |
| Loose file permissions | A private key warning or a silent rejection | Apply 700 and 600 with chmod |
| Password login off, no key | Only the publickey method appears | Add the key through console access |
| Another account or wrong remote | An HTTPS address or a second account on GitHub | Fix the address with git remote -v |
Why should you never share your private key?
A public key works like a door lock. You can hand it to as many people as you like. The private key, however, is the physical key that opens that lock. If you send it to someone, that person can enter the server in your name.
- First, do not paste private key content into support chats, forums, or AI tools.
- When you share error output, check that the
ssh -vlines hold no key content. Sharing a file path is fine, but sharing the file content is not. - Then, if you suspect a leak, generate a new pair and remove the old one from the server and from GitHub.
- Also, do not commit keys into a repository. If you did it by accident, you must replace the key.
In short, protect the private key like a password. If you do not use a password manager yet, our free password generator can create a strong value for your key passphrase.
How does ssh-copy-id add a key safely?
Copying a public key by hand is a common source of errors. So, if you still have access, use the ssh-copy-id tool. It ships with OpenSSH and adds the key to the right file with the right permissions.
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@example.com- The -i flag says which public key to add.
- Also, the tool creates the
.sshfolder and theauthorized_keysfile if they do not exist. - Afterwards, try the connection in a new terminal, and do not close the old session yet.
- If you cannot use the tool, append the key as a single line at the end of the file. Check that the line ending stays intact.
This removes hand-made permission and line mistakes. In addition, the tool prints how many keys it added.
Why does this error appear so often on a new computer?
Example scenario: a developer replaces a laptop, copies the projects, and sees the error on the first git pull. The private key from the old computer does not exist on the new one. Meanwhile, the GitHub account only holds the public key of the old device.
You have two options here. The first is to move the old key by a secure route. Alternatively, you can generate a new pair on the new device and add its public half to the account. That path is usually cleaner, because each device owns its key, and you can remove one lost device's key without touching the others.
- Generate a key with
ssh-keygen -t ed25519on the new device. - Add the content of the public file to your GitHub account or to the server's
authorized_keys. - Load the key into the agent with
ssh-add. - Test with
ssh -T git@github.com. - If you no longer use the old device, delete its key from the account.
Why does the error appear in CI/CD or automated deployment?
Automation tools behave like a separate computer, and they cannot reach your key. For this reason, you often meet the same error in deployment pipelines. In most cases the key was never added to the pipeline secrets, or it was added in the wrong form.
- First, create a separate key pair for the pipeline. Do not upload your personal key.
- Also keep the line breaks of the private key text. A key squeezed into one line is invalid.
- Give the public half read-only access where possible. GitHub Docs describes per-repository deploy keys for this purpose.
- On the first connection, ssh waits for a fingerprint confirmation, and that wait can freeze the pipeline.
If your release process has grown hard to manage, our AI automation services can help you simplify your workflows.
What happens if you forget the key passphrase?
The passphrase encrypts the private key file. If you forget it, you cannot open that file again, and that is a deliberate security feature. Trying brute force tools only wastes time and can count as attacking a system.
The right path is a new key pair. Then you add the new public key to the server or to GitHub and remove the old one. For that you need another way into the server, for example the panel console.
How do you read the real reason on the server side?
The client output only says "denied", and it never says why. The reason sits in the server's log. If you can reach the server another way, read the authentication logs. On many Linux distributions these live in auth.log or in the journalctl output.
Typically you will see lines similar to these:
- A line saying the user is unknown, which means the username is wrong.
- Another line pointing to the permissions of the authorization file, which means
StrictModesrejected the record. - Also a line saying the key was not accepted, which means the public key is missing or its format is broken.
- Finally, a line saying the user account is locked, which means you must unlock the account first.
The exact text can vary by distribution and version, so do not rely on one sentence. What matters is that the log gives you the precise reason that the client hides. If you need more detail temporarily, read the LogLevel option in the sshd_config manual.
Why does the diagnosis start with the most likely cause?
Random trials create two problems. They waste time, and each trial may change the setup a little more and hide the real cause. So we make reversible checks first, and only then change settings.
The username check changes nothing. Likewise, the ssh -v command only reads. The ssh-add -l command only lists. These three steps show most causes. Changing permissions or touching sshd settings comes later, because those steps can carry risk.
What are the most common mistakes with this error?
These are the repeated mistakes we see in the field. Knowing them speeds up the diagnosis a lot.
- First, putting the private key on the server and the public key on your own computer. You swap the files, and nothing works.
- Second, renaming the key file and forgetting to define it in the config.
- Third, using an HTTPS address on GitHub and blaming the SSH key.
- Also, adding the key to root and then logging in as another user.
- Then retrying again and again instead of reading the
ssh -voutput. - Finally, closing the working session first and testing the new setting afterwards.
Most of these mistakes take minutes to fix once you look closely. However, people overlook them when they hurry. Therefore, staying calm and following the order gives faster results than trial and error.
What if the error still continues?
If you followed the steps above in order and the error remains, look at a few rare causes. They are rare, and that is exactly why people miss them.
- The server may have turned off
PubkeyAuthentication. The sshd_config manual defines this option. AuthorizedKeysFilemay point to a non-default path, so your key sits in the wrong file.- Also, the user account may be locked, or its shell may be invalid.
- In addition, extra security layers such as SELinux may have changed the context of the home directory.
- If you can read the server log, you will see the real reason for the rejection there.
If you have access to the server logs, this is the fastest route. The reason is simple: sshd often writes the real cause. It shows a permission problem, a missing key, or a locked user as separate messages.
Which checklist gives lasting prevention?
A few small habits keep this error away. You can share the same list inside your team.
- First, generate a separate key for each device and add a meaningful comment.
- Second, protect keys with a passphrase and use ssh-agent.
- Define Host, User, and IdentityFile for every server in
~/.ssh/config. - Third, before you turn off password login on a server, test key login in a second session.
- Then clean old and unused keys from
authorized_keysand from your GitHub account on a regular basis. - When an employee leaves or a device goes missing, remove the matching key right away.
This list makes a difference even for a small team. For neighboring problems in software projects, also see our Git merge conflict guide and our Python ModuleNotFoundError guide.
When do you need professional help with this?
Adding a key to one server takes a few minutes. However, with dozens of servers, several team members, and a deployment pipeline, key management becomes a job of its own. At that point the authorization layout, key rotation, and access records matter.
If you want to build such an infrastructure or simplify an existing one, you can request a quote for our custom software development service. We listen to your needs first, then we send a clear scope in writing.
For a one-time error, the diagnosis order in this article is usually enough. If you cannot solve a case, remember to hide the private key content and the server address when you share output. For official sources, read the GitHub Docs troubleshooting page, the OpenSSH ssh manual, the sshd_config manual, and the ssh_config manual.



