GitHub SSH on macOS Step by Step, and How to Fix “Permission denied (publickey)”
A practical GitHub SSH setup guide for macOS that covers key generation, ssh-agent, GitHub key upload, testing the connection, and the exact fixes for the classic publickey authentication failure.
The real reason this error wastes so much time: the message
Permission denied (publickey)sounds like one failure, but it can come from several different mistakes in the SSH chain. If you do not check them in order, you end up editing random config files and making the setup worse.
What a healthy GitHub SSH setup actually needs
For GitHub SSH to work on a Mac, five things need to line up:
- you have an SSH key pair
- the private key is loaded or discoverable
- the public key is added to GitHub
- your Git remote uses
[email protected]:..., not HTTPS - SSH is using the key you think it is using
Miss any one of those and pushes start failing.
Step 1: check whether you already have SSH keys
Start by listing your SSH directory:
ls -la ~/.sshIf you already see files like id_ed25519 and id_ed25519.pub, do not blindly generate another key yet. First inspect what you already have:
cat ~/.ssh/id_ed25519.pubIf you do not have a key pair yet, generate one.
Step 2: create a modern SSH key
GitHub recommends Ed25519 when supported:
ssh-keygen -t ed25519 -C "[email protected]"When prompted for the file location, the default is usually fine:
/Users/yourname/.ssh/id_ed25519Then choose a passphrase. A passphrase is not mandatory, but it is a good idea unless this is a tightly controlled automation-only environment.
Step 3: start the SSH agent and add the key
On macOS:
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519If your macOS version uses older wording from prior guides, you may still see references to --apple-load-keychain. The important thing is that the key ends up available to SSH and stored in a way the machine can reuse safely.
Verify loaded keys:
ssh-add -lIf nothing shows up, GitHub authentication will probably still fail.
Step 4: add the public key to GitHub
Copy the public key:
pbcopy < ~/.ssh/id_ed25519.pubThen go to GitHub:
Settings -> SSH and GPG keys -> New SSH key
Paste the key and save it.
This is the simplest step, but it is also where people sometimes paste the private key by mistake. The file that ends in .pub is the one that belongs on GitHub.
Step 5: make sure your remote uses SSH
Check your current remote:
git remote -vIf you see something like:
https://github.com/yourname/yourrepo.gitthat is HTTPS, not SSH.
Switch it:
git remote set-url origin [email protected]:yourname/yourrepo.gitCheck again:
git remote -vStep 6: test the GitHub SSH connection
Run:
ssh -T [email protected]On the first connection, you may need to confirm GitHub’s host fingerprint. After that, a healthy response usually looks like:
Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.That is success.
If you still get Permission denied (publickey)
Now debug it methodically.
Check which key SSH is trying to use
Use verbose mode:
ssh -vT [email protected]This output tells you:
- which config files are being read
- which identities are being offered
- whether your expected key is even in the conversation
If the wrong key is being offered first or your real key is never tried, you likely need an explicit ~/.ssh/config.
A useful ~/.ssh/config for GitHub
Host github.com
HostName github.com
User git
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519After saving that file, retry:
ssh -T [email protected]Common mistakes that cause this exact failure
Wrong remote URL
You fixed the key but the repo is still pushing over HTTPS.
Wrong key on GitHub
You added an old key, a different machine’s key, or pasted the wrong file.
Key exists, but agent does not know about it
You generated the key and never loaded it:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519Multiple keys and no explicit config
SSH offers the wrong identity first and GitHub rejects the connection.
Final recommendation
Do not treat SSH setup as “done” when key generation finishes. Treat it as done when all three succeed:
ssh-add -l
ssh -T [email protected]
git push origin mainThat is when the chain is actually healthy. GitHub SSH is not hard once it works, but it becomes frustrating fast if you skip the order of operations.