Fix: Permission denied (publickey) – Git SSH Authentication Failed

The Error

You run git push, git pull, or git clone over SSH and get:

git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

You may also see just the first line:

Permission denied (publickey).

Or a variation when connecting to GitLab or Bitbucket:

git@gitlab.com: Permission denied (publickey,keyboard-interactive).

Why This Happens

SSH authentication failed. Git tried to connect to the remote server over SSH, and the server rejected the connection because it could not verify your identity.

This happens when:

  • You don’t have an SSH key. You never generated one on this machine.
  • Your SSH key isn’t added to the ssh-agent. The key exists on disk but your SSH client isn’t using it.
  • Your public key isn’t added to GitHub/GitLab/Bitbucket. The server doesn’t know about your key.
  • You have the wrong key loaded. You have multiple keys and SSH is presenting one the server doesn’t recognize.
  • Your remote URL uses SSH but you intended HTTPS. The remote is set to git@github.com:... instead of https://github.com/....

Fix 1: Check if You Have an SSH Key

First, check whether you already have an SSH key pair:

ls -la ~/.ssh

Look for a pair of files like:

  • id_ed25519 and id_ed25519.pub
  • id_rsa and id_rsa.pub

The .pub file is your public key (the one you give to GitHub). The other file is your private key (never share this).

If the ~/.ssh directory doesn’t exist or contains no key files, you need to generate one. Go to Fix 2.

If you do have a key pair, skip to Fix 3 to make sure it’s loaded, then Fix 4 to make sure GitHub has it.

Fix 2: Generate a New SSH Key

Generate an Ed25519 key (recommended over RSA for better security and shorter keys):

ssh-keygen -t ed25519 -C "your_email@example.com"

When prompted for a file location, press Enter to accept the default (~/.ssh/id_ed25519). Set a passphrase when prompted — it adds a layer of protection if someone gets access to your private key file.

If you’re on an older system that doesn’t support Ed25519, use RSA with a 4096-bit key:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Verify the key was created:

ls -la ~/.ssh

You should see id_ed25519 and id_ed25519.pub (or id_rsa and id_rsa.pub).

Fix 3: Add Your Key to the ssh-agent

The ssh-agent manages your SSH keys in memory so you don’t have to specify the key file manually every time.

macOS

eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

The --apple-use-keychain flag stores the passphrase in your macOS Keychain so you won’t be prompted again after a restart.

To make this persist across reboots, add the following to ~/.ssh/config (create the file if it doesn’t exist):

Host github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Linux

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

If you want the agent to start automatically when you log in, add eval "$(ssh-agent -s)" to your ~/.bashrc or ~/.zshrc.

Windows (Git Bash)

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

If you’re using Windows PowerShell or the built-in OpenSSH, the ssh-agent is a Windows service:

# Run in an elevated PowerShell
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Fix 4: Add Your Public Key to GitHub / GitLab / Bitbucket

Copy your public key to the clipboard:

# macOS
pbcopy < ~/.ssh/id_ed25519.pub

# Linux (requires xclip)
xclip -selection clipboard < ~/.ssh/id_ed25519.pub

# Windows (Git Bash)
clip < ~/.ssh/id_ed25519.pub

# Or just print it and copy manually
cat ~/.ssh/id_ed25519.pub

Then add it to your hosting provider:

GitHub:

  1. Go to github.com/settings/keys
  2. Click New SSH key
  3. Give it a title (e.g., “Work Laptop”)
  4. Paste your public key
  5. Click Add SSH key

GitLab:

  1. Go to gitlab.com/-/user_settings/ssh_keys
  2. Paste your public key in the Key field
  3. Set an optional expiration date
  4. Click Add key

Bitbucket:

  1. Go to Personal settings > SSH keys
  2. Click Add key
  3. Paste your public key
  4. Click Add key

Fix 5: Test the Connection

Verify that SSH authentication works:

# GitHub
ssh -T git@github.com

# GitLab
ssh -T git@gitlab.com

# Bitbucket
ssh -T git@bitbucket.org

A successful GitHub response looks like:

Hi username! You've successfully authenticated, but GitHub does not provide shell access.

If you see Permission denied (publickey) again, SSH is still not using the right key. Run the connection with verbose output to debug:

ssh -vT git@github.com

Look for these lines in the output:

  • Offering public key: /home/you/.ssh/id_ed25519 — confirms SSH is trying your key.
  • Server accepts key — the server recognized your key.
  • No more authentication methods to try — none of your keys were accepted.

If SSH isn’t offering any keys, go back to Fix 3. If it offers a key but the server rejects it, the public key on GitHub doesn’t match — go back to Fix 4 and re-add it.

Fix 6: Use HTTPS Instead of SSH

If you can’t get SSH working or just prefer a simpler setup, switch your remote to HTTPS:

# Check your current remote URL
git remote -v

# If it shows git@github.com:user/repo.git, change it to HTTPS:
git remote set-url origin https://github.com/user/repo.git

For GitLab:

git remote set-url origin https://gitlab.com/user/repo.git

With HTTPS, Git authenticates using a personal access token or credential manager instead of SSH keys. GitHub no longer accepts passwords for HTTPS Git operations — you’ll need a personal access token or the GitHub CLI (gh auth login).

Still Not Working?

Wrong file permissions on ~/.ssh

SSH refuses to use key files that are readable by other users. Fix the permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/config

If permissions are wrong, SSH silently ignores the key file. This is a common issue on shared systems or when copying keys between machines.

Multiple GitHub accounts

If you have both a personal and a work GitHub account, SSH doesn’t know which key to use. Configure ~/.ssh/config with separate host aliases:

# Personal account
Host github.com-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal

# Work account
Host github.com-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work

Then update your remotes to use the alias:

# For personal repos
git remote set-url origin git@github.com-personal:your-personal-user/repo.git

# For work repos
git remote set-url origin git@github.com-work:your-work-user/repo.git

Corporate firewall blocking port 22

Some corporate networks block outgoing connections on port 22 (the default SSH port). GitHub and GitLab offer SSH over HTTPS port 443 as a workaround.

For GitHub, add this to ~/.ssh/config:

Host github.com
  HostName ssh.github.com
  Port 443
  User git

For GitLab, use:

Host gitlab.com
  HostName altssh.gitlab.com
  Port 443
  User git

Test the connection:

ssh -T -p 443 git@ssh.github.com

WSL2 SSH keys are separate from Windows

SSH keys inside WSL2 are stored in the Linux filesystem (~/.ssh inside your WSL distro), completely separate from your Windows keys (C:\Users\YourName\.ssh). If you set up keys in Windows but are running Git from WSL2, you need to either:

  • Generate a new key pair inside WSL2 and add it to GitHub, or
  • Copy your Windows keys into WSL2 and fix permissions:
cp /mnt/c/Users/YourName/.ssh/id_ed25519* ~/.ssh/
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Wrong remote URL

Your remote might be pointing to the wrong host or using the wrong format. Check it:

git remote -v

Make sure it matches the expected format:

  • SSH: git@github.com:username/repo.git
  • HTTPS: https://github.com/username/repo.git

A common mistake is having git@github.com/username/repo.git (forward slash instead of colon after the host). The correct SSH format uses a colon.

Verbose debugging

If none of the above fixes work, run a verbose SSH connection to see exactly what’s happening:

ssh -vvT git@github.com

The -vv flag gives you detailed debug output. Look for:

  • Which config files are being loaded
  • Which identity files SSH is trying
  • Why the server rejected the authentication
  • Whether SSH is connecting to the right host and port

Share this output (redact any sensitive paths) if you need to ask for help.


Related: Fix: git push rejected – non-fast-forward error

Related Articles