Back to blog

How to Fix Permission Denied Publickey SSH Connection Error

One of the most common blockers when pushing code to GitHub or logging into a remote Linux virtual machine is the dreaded SSH connection failure: "Permission denied (publickey).".

This error indicates that the SSH protocol handshake failed. The remote server requested a secure public key credential for authentication, but your local computer failed to present a matching private key.

In this guide, we will examine why SSH authentication fails, verify your local key configurations, generate modern secure keys, configure the SSH agent, and debug connections step-by-step.

Why Does SSH Authentication Fail?

When you connect to a server via SSH (e.g., executing ssh user@server or pushing code via git push), a cryptographic exchange occurs:

  1. The server reads the username and looks for authorized public keys stored in its local configuration (such as the ~/.ssh/authorized_keys file or your GitHub profile settings).
  2. The server sends a encrypted challenge message to your local machine.
  3. Your local SSH client must decrypt this challenge using the corresponding private key stored locally.

If your local machine has no private key, has not loaded the key into the active memory agent, or the remote server lacks the matching public key, the authentication loop fails, raising the Permission denied error.

Step 1: Check for Existing SSH Keys

First, check if your local machine already has SSH keys generated:

# List files in your local SSH directory
ls -la ~/.ssh

Look for files with these names:

  • Ed25519 (Recommended): id_ed25519 (private key) and id_ed25519.pub (public key).
  • RSA (Legacy): id_rsa and id_rsa.pub.

If these files are missing, proceed to Step 2. If you already have these files, skip to Step 3.

Step 2: Generate a New SSH Key Pair

If you lack SSH keys, generate a new pair using the Ed25519 algorithm. Ed25519 is more secure and has better performance than legacy RSA:

ssh-keygen -t ed25519 -C "your_email@example.com"
  • When prompted to "Enter file in which to save the key", press Enter to accept the default directory.
  • When prompted for a passphrase, either enter a secure passphrase for extra safety or press Enter twice to leave it empty.

Step 3: Add Your Private Key to ssh-agent

The ssh-agent is a background helper program that keeps your decrypted private keys loaded in memory, preventing you from typing your passphrase continuously.

Start the agent:

eval "$(ssh-agent -s)"

Add your newly created private key to the agent:

ssh-add ~/.ssh/id_ed25519

Step 4: Configure the Public Key on GitHub or Servers

Now, copy the contents of your public key (the file ending in .pub). Never share or copy your private key.

# Display the public key contents to your terminal window
cat ~/.ssh/id_ed25519.pub

Copy the entire output string, which starts with ssh-ed25519.

For GitHub / GitLab integrations:

  1. Navigate to GitHub Settings -> SSH and GPG Keys.
  2. Click New SSH Key.
  3. Give it a descriptive Title (e.g., "Work Laptop") and paste the copied string into the Key field.

For direct Linux servers logins:

Log into the remote server using password authentication and append your public key string to the authorized_keys file:

echo "YOUR_COPIED_PUBLIC_KEY_STRING" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Step 5: Test and Debug the Connection

To verify that the configuration was successful, run a test connection:

# Test connection to GitHub
ssh -T git@github.com

If it succeeds, you will see a message: "Hi username! You've successfully authenticated...".

If it still fails, run the command in Verbose Mode by adding the -v flag. This prints the entire authentication sequence, highlighting exactly where it fails:

ssh -Tv git@github.com

In the verbose output, look for lines starting with debug1:. Search for lines like debug1: Authentications that can continue: publickey and trace which local private key files the client attempted to load.

Conclusion

SSH key issues are resolved by verifying the key handshake chain. By checking for keys in ~/.ssh/, generating modern secure Ed25519 keys using ssh-keygen, loading them into the active ssh-agent, adding the public key string to GitHub settings or authorized_keys servers files, and using ssh -v to trace handshakes, you can resolve connection permission issues.