How to Resolve Git ‘Permission denied (publickey)’ SSH Authentication Errors

Encountering the Permission denied (publickey) error when attempting Git operations like git clone or git push using an SSH URL (e.g., git@github.com:...) is a common issue related to SSH key authentication.

This message indicates that the remote server could not verify your identity using SSH keys.

This article explains the underlying causes of this error and outlines several effective solutions and troubleshooting steps based on common practices for resolving SSH authentication problems with Git.

Understanding the SSH Authentication Process

When you connect to a Git remote repository using an SSH URL, the process relies on public-key cryptography:

  • You generate a pair of keys: a private key (kept secret on your local machine) and a public key (shared with the remote service, like GitHub or GitLab).
  • During connection, your Git client uses the private key to prove its identity.
  • The remote server checks if the corresponding public key is registered and authorized for access to the requested repository.

The Permission denied (publickey) error typically means a breakdown occurred in this process: your client might not be presenting the correct key, the key might not be accessible, or the server might not recognize the key you’re presenting.

Read: How to use scp command in Linux to transfer files securely using ssh

Common Solutions and Troubleshooting Steps

Here are various methods to address the public key authentication failure:

1. Generate and Register SSH Keys

The most fundamental step is ensuring you have an SSH key pair generated and the public key registered with your Git hosting service.

  1. Check for Existing Keys: Navigate to your SSH directory (usually ~/.ssh) and list files. Look for files like id_rsa.pub, id_ecdsa.pub, or id_ed25519.pub.
    cd ~/.ssh
    ls -al
  2. Generate a New Key Pair (if needed): If no suitable key exists, generate one. Using Ed25519 is often recommended, but RSA is also common. Replace the email address with the one associated with your Git service account.
    # Recommended: Ed25519
    ssh-keygen -t ed25519 -C "your_email@example.com"
    
    # Alternative: RSA (specify bit strength)
    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

    Press Enter to accept the default file location (e.g., ~/.ssh/id_ed25519) and optionally set a secure passphrase when prompted.

  3. Copy the Public Key: Display the contents of your public key file (the one ending in .pub) and copy it to your clipboard. Use the command appropriate for your operating system:
    # macOS
    pbcopy < ~/.ssh/id_ed25519.pub
    
    # Linux (requires xclip)
    xclip -sel clip < ~/.ssh/id_ed25519.pub
    
    # Windows (Git Bash)
    clip < ~/.ssh/id_ed25519.pub
    
    # Windows (PowerShell)
    Get-Content ~/.ssh/id_ed25519.pub | Set-Clipboard

    Ensure you copy the key generated in the previous step (e.g., id_ed25519.pub or id_rsa.pub).

  4. Add Public Key to Git Service: Go to your Git hosting service’s website (GitHub, GitLab, Bitbucket, etc.). Navigate to your account settings, find the section for SSH keys (often under “SSH and GPG keys”), and add a new SSH key, pasting the copied public key content. Give it a descriptive title (e.g., “Work Laptop”).
  5. Configure Local Git Identity (if not set): Ensure your local Git client knows your name and email.
    git config --global user.name "Your Name"
    git config --global user.email "your_email@example.com"

    Restarting your terminal might be necessary for changes to take effect.

  6. Repository Deploy Keys (Alternative): For specific repository access (e.g., automated deployment), you might add the public key as a “Deploy Key” within the repository’s settings instead of your main account settings.

This process ensures the server has your public key and can verify connections authenticated by your corresponding private key.

Read: How to configure SSH-key based authentication on Ubuntu 20.10

2. Use the SSH Agent

The SSH agent is a background program that holds your private keys and manages their passphrases, making them readily available for SSH connections.

  1. Start the SSH Agent (if not running):
    eval "$(ssh-agent -s)"

    This should output an agent PID.

  2. Add Your Private Key to the Agent: Tell the agent about your private key file. Replace id_ed25519 with your specific private key filename if different.
    ssh-add ~/.ssh/id_ed25519

    If your key has a passphrase, you’ll be prompted to enter it here.

    Note on Flags: On macOS, ssh-add -K ~/.ssh/id_ed25519 might be used to store the passphrase in the Keychain. On some systems (like Raspberry Pi or older setups), ssh-add -k might be needed instead.
  3. Verify the Key is Added: List the keys managed by the agent.
    ssh-add -l

    You should see the fingerprint of the key you added.

Adding the key to the agent ensures it’s actively available for Git operations, which can resolve issues where the system isn’t automatically picking up the correct key.

Read: How to Configure Git to Use Specific SSH Private Keys

3. Switch to HTTPS URLs

If setting up SSH keys is proving difficult, or if you only need read-only access, using the HTTPS URL for the repository is a viable alternative. HTTPS uses different authentication methods (typically username/password or Personal Access Tokens).

  • When Cloning: Use the HTTPS URL provided by the Git service.
    git clone https://github.com/USERNAME/REPOSITORY.git
  • For Existing Repositories: Update the remote URL. Check the current URL first, then set the new one.
    # Check current remote URL
    git remote -v
    
    # Change 'origin' remote to HTTPS
    git remote set-url origin https://github.com/USERNAME/REPOSITORY.git

This bypasses SSH key validation entirely. Note that many services now require Personal Access Tokens (PATs) instead of passwords for HTTPS authentication.

4. Verify SSH Connection and Configuration

Use the SSH command itself with verbose output to diagnose connection problems.

ssh -vT git@github.com

Replace git@github.com with the appropriate host if you’re using a different service (e.g., git@gitlab.com, git@ssh.dev.azure.com).

Carefully examine the output. It will show:

  • Which configuration files are being read (e.g., ~/.ssh/config).
  • Which identity files (private keys) it’s attempting to use.
  • Detailed steps of the connection attempt and where it might be failing.

This is invaluable for identifying issues like:

  • SSH trying to use the wrong key file.
  • Incorrect permissions on key files or SSH directory.
  • Configuration issues in ~/.ssh/config (e.g., an incorrect IdentityFile specified for the host).
  • Network-level blocks or firewall issues.

5. Address Windows-Specific SSH Client Conflicts

Windows environments can sometimes have multiple SSH clients installed (e.g., the one bundled with Git for Windows, and the one built into Windows/OpenSSH). Git might be using a different client than the one you configured or added keys to via the SSH agent service.

  • Force Git to Use Windows OpenSSH: Configure Git globally to use the standard Windows SSH executable.
    git config --global core.sshCommand "'C:\Windows\System32\OpenSSH\ssh.exe'"

    Alternatively, edit your global ~/.gitconfig file and add/modify the sshCommand under the [core] section:

    [core]
        sshCommand = 'C:\\Windows\\System32\\OpenSSH\\ssh.exe'

    Ensure the path to ssh.exe is correct for your system.

  • Git Installer Option: During the Git for Windows installation, choose the option “Use external OpenSSH” instead of the bundled one if you intend to use the Windows SSH agent service.
  • Environment Variable Consistency: Ensure the HOME environment variable is consistently defined across different shells (Git Bash, PowerShell, Command Prompt) as SSH relies on this to find the .ssh directory.
  • PowerShell Specifics: When using PowerShell:
    • Ensure the ssh-agent service is running:
      Get-Service -Name ssh-agent | Set-Service -StartupType Manual
      Start-Service ssh-agent
    • Add your key using its full path:
      ssh-add C:\Users\YourUser\.ssh\your_private_key
    • Optionally, configure ~/.ssh/config to specify the key for the host, or use the -c core.sshCommand flag during clone/fetch/push to specify the key inline:
      git clone -c core.sshCommand="ssh -i C:\\Users\\YourUser\\.ssh\\your_private_key" git@github.com:USER/REPO.git

6. Advanced SSH Configuration and Algorithm Compatibility

Sometimes, issues arise from server-side changes or complex multi-key setups.

  • Algorithm Deprecation: Newer versions of OpenSSH (like 8.8+) have deprecated older algorithms (e.g., SHA-1 RSA signatures). If the remote server hasn’t updated or requires older algorithms, you might need to explicitly enable them in your ~/.ssh/config file for that specific host:
    Host git.example.com
        HostkeyAlgorithms +ssh-rsa
        PubkeyAcceptedAlgorithms +ssh-rsa

    Replace git.example.com with the actual remote host. Alternatively, regenerate your key pair using a more modern algorithm like Ed25519 (see Step 1).

  • Specify Identity File per Host: If you use different keys for different hosts, define them in ~/.ssh/config:
    Host github.com
        HostName github.com
        User git
        IdentityFile ~/.ssh/github_key
    
    Host gitlab.com
        HostName gitlab.com
        User git
        IdentityFile ~/.ssh/gitlab_key
  • SSH Agent Forwarding: If you are SSH’d into an intermediary server and need to perform Git operations from there using your *local* machine’s keys, enable agent forwarding. Edit your local ~/.ssh/config or /etc/ssh/ssh_config and set ForwardAgent yes for the relevant host. Be cautious, as this has security implications.

Read: How To Run a Github-Actions Step, Even If The Previous Step Fails, While Still Failing The Job

7. Use Alternative Authentication: PATs or GitHub CLI

If SSH continues to be problematic, consider these alternatives:

  • Personal Access Tokens (PATs): Generate a PAT from your Git service provider (Settings -> Developer settings -> Personal access tokens). Use this token instead of a password when cloning or pushing via HTTPS:
    # Clone with token
    git clone https://YOUR_TOKEN@github.com/USERNAME/REPOSITORY.git
    
    # Update remote for existing repo
    git remote set-url origin https://YOUR_TOKEN@github.com/USERNAME/REPOSITORY.git

    You might also be prompted for a username (use your Git service username) and password (use the PAT).

  • GitHub CLI (`gh`): Install the official GitHub CLI. After logging in once (`gh auth login`), it handles authentication automatically for Git operations on GitHub repositories.
    # Install (example for macOS with Homebrew)
    brew install gh
    
    # Login (interactive)
    gh auth login
    
    # Clone
    gh repo clone USERNAME/REPOSITORY

Read: How to discard changes in Git

8. Check Permissions and Execution Context

  • Avoid `sudo`: Do not run Git commands with `sudo` unless necessary and fully understood. Running ssh-keygen as your user and then sudo git push means Git runs as the `root` user, who likely doesn’t have access to your user’s SSH keys or agent. If `sudo` is required, ensure consistency or use `su` to become root first.
  • File/Directory Permissions: Incorrect permissions on your ~/.ssh directory (should be 700) or private key files (should be 600) can prevent SSH from using them. While less common as a direct cause for this specific error, it’s good practice to ensure they are correct. In some specific server environments, broader home directory permissions might be needed (e.g., chmod -R 700 /home/user/ was mentioned for one EC2 case).
  • Root Key Location (Specific Environments): In some environments (like certain cloud VMs), if operations run as root, you might need to copy your user’s SSH keys to the root user’s SSH directory:
    sudo cp ~/.ssh var wpcf7 = {"apiSettings":{"root":"https:\/\/net2.com\/wp-json\/contact-form-7\/v1","namespace":"contact-form-7\/v1"},"cached":"1"};