GitHub

How to Add SSH Key to GitHub

How to Add SSH Key to GitHub

Git can log in to GitHub with a key instead of a password or token. Generate a pair with ssh-keygen, paste the public file into Settings, SSH and GPG keys on your account, and pushes and pulls on private repositories stop asking who you are.

The setup is the same on macOS, Linux and Windows, apart from a few commands.

Most guides skip one thing. GitHub treats authentication and commit signing as separate key types, so a key meant for both must be uploaded twice (GitHub Docs, as of October 2026).

How to Check for an Existing SSH Key

Run ls -al ~/.ssh in a terminal. If a public key file shows up in the listing, you might already have a key you can reuse.

Look for id_ed25519.pub, id_ecdsa.pub or id_rsa.pub. Each has a private twin with the same name and no .pub extension, and only the .pub file ever goes to GitHub.

If the terminal says ~/.ssh does not exist, there is no key pair in the default location, according to GitHub Docs. Generate a new one in the next step.

The folder lives at ~/.ssh on macOS and Linux. On Windows it is C:\Users\YOURNAME\.ssh, and Git Bash maps ~ to the same place.

You can also run ssh-add -l to see what the ssh-agent holds right now. “The agent has no identities” only means nothing is loaded yet. A key can still be sitting on disk.

And a key on disk doesn’t prove GitHub knows about it. Run ssh-keygen -lf ~/.ssh/id_ed25519.pub to print its fingerprint, then compare it with the fingerprints listed under Settings, SSH and GPG keys.

Which SSH Key Type Should You Use?

For almost every new key, pick Ed25519. OpenSSH 9.5 (released 4 October 2023) made it the default for ssh-keygen, and the algorithm has been supported since OpenSSH 6.5 in January 2014 (OpenSSH release notes).

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →
Key typessh-keygen flagGitHub statusBest fit
Ed25519-t ed25519Supported, used in GitHub Docs examplesDefault for new keys
RSA-t rsa -b 4096Supported, SHA-2 signatures required for newer keysClients too old for Ed25519
ECDSA-t ecdsaSupportedKeeping an existing key
Ed25519-SK-t ed25519-skSupported, key must be attachedHardware security key

RSA stuck around mostly out of habit. GitHub’s own 2021 traffic breakdown put ssh-ed25519 at 7.3% of requests, ssh-rsa at 45% and rsa-sha2 at 47% (GitHub blog, 2021).

RSA still works, with one condition

RSA keys generated after November 2, 2021 must use SHA-2 signatures (GitHub Docs). Older keys, with a valid_after date before that day, may keep using any signature algorithm. OpenSSH 7.2 and newer already sign with SHA-2, so a recent client handles this without any help from you.

The Go SSH client did not support RSA with SHA-2 when GitHub announced the change, so GitHub told Go users to switch to Ed25519.

DSA keys no longer work

GitHub dropped DSA (ssh-dss) on March 15, 2022, and new DSA keys cannot be added to a personal account. The 2021 announcement put DSA at an 80-bit security level (GitHub blog, 2021).

If an old machine only has a DSA key, generate an Ed25519 key instead of hunting for a workaround.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Hardware security keys

An ed25519-sk key ties authentication to a physical FIDO2 device. GitHub Docs notes that the hardware key must be attached to the computer every time the key pair is used.

How to Generate a New SSH Key

YouTube player

One command creates the key pair:

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

The -t ed25519 flag sets the algorithm. The -C flag adds a comment at the end of the public key, usually an email address or a machine name.

ssh-keygen starts by asking where to save the file. Press Enter to accept ~/.ssh/id_ed25519. If a key already sits at that path, type a new name or pass one up front with -f ~/.ssh/id_ed25519_work.

▶ GIT EXPLAINED

If you commit, branch, or merge code every day, it helps to know how Git came to be. This video covers how Linus Torvalds created Git in just 10 days after a license dispute and explains how its data model actually works.

Linus Torvalds Built Git in Days Out of Spite
Built in 10 Days Out of Spite. Git and its data model explained in plain language.

Next it wants a passphrase, typed twice. The passphrase encrypts the private key file on disk, so a copied file is useless without it.

An empty passphrase works, but anyone who gets the file can then authenticate as you. I’d set one. The ssh-agent in the next step means you type it once per session instead of on every push.

The command prints the fingerprint and a randomart image, and writes two files: id_ed25519 (private) and id_ed25519.pub (public).

Keep the file name consistent in every later command. GitHub docs issue 1086 reported a page where the generate step saved id_ed25519 but the next command pointed at id_rsa, which returned “No such file or directory”. GitHub has since fixed that page.

Generate a key for a hardware security key

Plug the device in first, then run ssh-keygen -t ed25519-sk -C "your_email@example.com". Touch the button on the device when prompted.

If the command fails with “invalid format” or “feature not supported”, the device does not support Ed25519. Run ssh-keygen -t ecdsa-sk -C "your_email@example.com" instead (GitHub Docs).

The remaining prompts match the standard flow, and the upload to GitHub works the same way.

How to Add the SSH Key to the ssh-agent

The ssh-agent keeps a decrypted copy of the private key in memory, so Git stops asking for the passphrase on every operation.

  1. eval "$(ssh-agent -s)" starts the agent and prints its process ID.
  2. ssh-add ~/.ssh/id_ed25519 loads the key.
  3. ssh-add -l -E sha256 confirms it is loaded, shown as a SHA256 fingerprint.

macOS

Add the key to the Keychain so the passphrase survives a reboot: ssh-add --apple-use-keychain ~/.ssh/id_ed25519.

The --apple-use-keychain flag exists only in Apple’s own ssh-add. If you see ssh-add: illegal option -- apple-use-keychain, you are running a different ssh-add, such as one installed through Homebrew or MacPorts. Call Apple’s version by its full path, /usr/bin/ssh-add. On macOS releases before Monterey (12.0), the flag is -K (GitHub Docs).

Then create or edit ~/.ssh/config:

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

Write Host github.com, not Host *.github.com. One user in GitHub docs issue 23512 copied the wildcard version and still got a password prompt on clone, because the pattern needs a subdomain and plain github.com never matches it.

Linux

Use the same eval and ssh-add lines. An agent started this way ends with the shell session, so repeat them in a new terminal unless your desktop environment already runs an agent.

If ssh complains about an unprotected private key file, chmod 600 ~/.ssh/id_ed25519 fixes the permissions.

To limit how long the key stays loaded, add a lifetime in seconds: ssh-add -t 3600 ~/.ssh/id_ed25519.

Windows

Git Bash, the shell bundled with Git for Windows, runs the same eval and ssh-add lines shown above. That’s the easy route.

The built-in Windows OpenSSH agent in PowerShell takes a bit more work. In an elevated window, start the service with Get-Service -Name ssh-agent | Set-Service -StartupType Manual followed by Start-Service ssh-agent. Then add the key from a normal window: ssh-add $env:USERPROFILE\.ssh\id_ed25519.

GitHub Docs tells Windows users to run ssh-add from a terminal window without elevated permissions.

How to Add the Public Key to Your GitHub Account

Copy the contents of the .pub file, then paste it into Settings, SSH and GPG keys, New SSH key. The direct address is github.com/settings/keys.

Use whichever copy command matches your system:

  • macOS: pbcopy < ~/.ssh/id_ed25519.pub
  • Linux (with xclip installed): xclip -selection clipboard < ~/.ssh/id_ed25519.pub
  • Windows (Git Bash): clip < ~/.ssh/id_ed25519.pub
  • Windows (PowerShell): cat ~/.ssh/id_ed25519.pub | clip
  1. Copy the public key with the command for your system.
  2. Click your profile photo in the upper-right corner of any GitHub page, then click Settings.
  3. Click SSH and GPG keys in the sidebar.
  4. Click New SSH key (or Add SSH key if the list is empty).
  5. Enter a title that names the machine, such as Work Laptop.
  6. Select the key type: Authentication Key or Signing Key.
  7. Paste the key into the Key field.
  8. Click Add SSH key and confirm access to your account if GitHub prompts for it.

An authentication key lets the machine push and pull. A signing key verifies commits. To use one key for both, upload it twice (GitHub Docs).

Paste only the .pub file. The private key never leaves your machine.

Upload from the command line

The GitHub CLI skips the browser entirely, once you have authenticated it with gh auth login.

gh ssh-key add ~/.ssh/id_ed25519.pub --type authentication

Use --type signing for a signing key. GitHub deletes SSH keys that go unused for a year (GitHub Docs), so a key on a laptop you rarely open may need to be added again.

How to Verify the Connection and Switch Repositories to SSH

Run ssh -T git@github.com. A working key prints your username and a note that GitHub does not provide shell access.

Test the connection

The first time you connect, ssh stops with “The authenticity of host ‘github.com’ can’t be established” and prints a fingerprint. GitHub’s testing page shows the ED25519 fingerprint as SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.

Match it against GitHub’s published SSH key fingerprints before typing yes. ssh then saves the host key in known_hosts, so the prompt only returns if that entry changes.

The expected output looks like this:

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

Read the username in that message. A name that isn’t yours means the key sits on a different account. Exit code 1 is normal, because GitHub runs no remote command (GitHub Docs).

Always connect as git, never as your own username. And if the key isn’t loaded in the agent, ssh asks for the passphrase instead.

Switch an existing repository from HTTPS to SSH

Run git remote -v to see which address a local repository uses. Git stores the address of each remote repository under a short name, usually origin.

An HTTPS address looks like https://github.com/OWNER/REPOSITORY.git. The SSH form is git@github.com:OWNER/REPOSITORY.git.

Change it with one command, then run git remote -v again to confirm:

git remote set-url origin git@github.com:OWNER/REPOSITORY.git

For a fresh copy, cloning with the SSH address skips the switch entirely.

How to Authorize the Key for an Organization With SAML SSO

An organization that uses SAML single sign-on accepts an SSH key only after you authorize that key for the organization. Without it, the key stays blocked on the organization’s repositories even though it works on your own.

Go to Settings, SSH and GPG keys, click Configure SSO to the right of the key, then click Authorize next to the organization.

If the Configure SSO button is missing, authenticate once through your identity provider (the SAML system the organization uses for sign-in) so GitHub can link your identity. Once linked, only authorized SSH keys and personal access tokens work with that organization, even if SAML is not enforced (GitHub Docs). And if the enterprise combines SSO with an IP allow list, your IP must also be allowed at the enterprise level.

Revocation is final for that key. When an organization revokes the authorization, you cannot reauthorize the same key and have to generate and authorize a new one.

SSH certificates signed by an organization’s own certificate authority skip this step, per GitHub Docs.

Why Permission Denied (publickey) Appears and How to Fix It

Permission denied (publickey) means GitHub received no key it recognizes for your account.

SymptomCauseFix
Denied when connecting with your own usernameWrong user in the commandConnect as git@github.com
ssh-add -l lists no identitiesAgent stopped or key not loadedStart the agent, run ssh-add
Verbose log offers a different key fileWrong key offeredSet IdentityFile and IdentitiesOnly yes for github.com in ~/.ssh/config
Key already in usePublic key attached to another account or a deploy keyRemove it from the other account or repository, or generate a fresh key if you cannot
Bad file number or a timeoutFirewall blocks port 22Use SSH over port 443

Read the verbose output

  1. Run ssh -vT git@github.com.
  2. Look for “Authentications that can continue: publickey”, which confirms GitHub wants a key.
  3. Scan the “Offering public key” lines, or filter them with ssh -vT git@github.com 2>&1 | grep "Offering".
  4. If your key file’s path never appears, ssh never tried it.

One variant deserves its own note. “Agent admitted failure to sign using the key” shows up in the log just before the denial, and GitHub calls it a known problem with certain Linux distributions.

Reload the key into the agent and test again.

Port 22 blocked

Some firewalls reject SSH outright. GitHub serves SSH on the HTTPS port as well, at a different hostname: ssh.github.com, not github.com.

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

If that prints your username, force every GitHub connection through it by adding this block to ~/.ssh/config:

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

The first connection after the switch may warn that the host was not found in known\_hosts, or that it is known under another name. Answering yes is safe when the fingerprint matches one GitHub publishes (GitHub Docs).

GitHub Enterprise Server and GitHub Enterprise Cloud with data residency do not support SSH over the HTTPS port, so this fix won’t help there.

SSH Key or Personal Access Token: Which Fits Your Workflow?

Use an SSH key on a machine you own, and a token or deploy key everywhere else. The choice comes down to who holds the credential and how much it can reach.

MethodSetupScopeBest for
SSH keyKey pair plus ssh-agentWhole accountYour own laptop
HTTPS with a personal access tokenToken plus credential helperSet per tokenNetworks that block port 22
Deploy keyOne key per repositorySingle repositoryServers and CI runners

SSH key

Once the key sits in the ssh-agent, the prompts stop. There is also no token to store, rotate or paste into a config file, which is the part I like most.

The downsides are smaller. Port 22 is sometimes blocked, though the 443 fallback covers that. And the private key lives on disk, so a lost laptop means revoking it.

Personal access token

HTTPS is easier to set up than SSH and usually passes through strict firewalls and proxies, according to GitHub Docs. It works wherever HTTPS works, and each token carries its own scope.

Git does ask for credentials on every pull and push until a credential helper such as Git Credential Manager caches them. Password-based authentication for Git was also removed, so the password prompt now takes a token.

Creating a personal access token takes a few minutes in GitHub’s settings.

Deploy keys

A deploy key is an SSH key that grants access to a single repository. It can be read-only, and that is the setting to prefer. In the web interface, new deploy keys are read-only unless you tick Allow write access.

A deploy key with write access can perform the same actions as an organization member with admin access, or a collaborator on a personal repository (GitHub REST API docs). Deploy keys are also immutable, so a wrong setting means deleting the key and adding it again.

Read the Docs ran into this in 2025. Private repositories added to Read the Docs Business before April 23, 2025 could end up with a write-access deploy key, and the team migrated existing keys to read-only where possible (Read the Docs, July 2025).

The upsides are a narrow scope, a read-only option and no personal account involved. The catch is one key per repository, and GitHub allows each public key on only one account or deploy key.

Skip the shortcut of copying your personal key onto a server or CI runner. A deploy key limits the damage to one repository.

You may not need a key at all

GitHub Desktop users can clone repositories without handling SSH keys, according to GitHub’s own troubleshooting page.

If GitHub Desktop is your only Git client, the whole key setup above is optional.

SSH Key FAQ

What exactly does GitHub store when you add an SSH key?

GitHub stores only the public key. The private key stays on your machine.

The public key text alone cannot authenticate anyone, because every login needs the matching private file.

Can I use different SSH keys for multiple GitHub accounts?

Yes. Generate one key per account, since GitHub attaches each public key to a single account.

Then give each key a Host alias in ~/.ssh/config with HostName set to github.com, its own IdentityFile, and IdentitiesOnly yes. Clone through the alias, for example git@github-work:ORG/REPO.git.

How do I delete or replace an SSH key on GitHub?

Open Settings, SSH and GPG keys, then click Delete next to the key.

To rotate, add the new key first, confirm it with ssh -T git@github.com, and delete the old one last.

How do I sign commits with an SSH key?

Upload the public key as a Signing Key, then point Git at it:

git config --global gpg.format ssh

git config --global user.signingkey ~/.ssh/id_ed25519.pub

git config --global commit.gpgsign true

Does GitHub Enterprise Server use the same steps?

Yes, with one change. Keys go to your account on the instance, and the test command uses your instance hostname: ssh -T git@HOSTNAME.

Can I generate the key with PuTTYgen on Windows?

Yes. Copy the text from the box labeled for pasting into an OpenSSH authorized\_keys file, not from the saved public key file.

RSA keys need PuTTY 0.75 or later to sign with SHA-2 (GitHub blog, 2021).

Which SSH Keys Should Stay on Your Account?

Keep one SSH key per machine you still use, and nothing else. Every extra key on the account is a credential that reaches every repository you can access.

When you review the list, start by deleting keys from retired machines. Replace legacy key types with Ed25519 next, and switch deploy keys to read-only last.

The order follows blast radius. A key from a lost laptop opens the whole account, while a legacy key type is a smaller risk on a machine you still control.

One key per machine has a cost: more entries to review. The payoff is that a lost laptop means deleting one entry instead of rotating a shared key everywhere.

This advice was checked against GitHub Docs in October 2026, and a change to the supported key types would alter the second step. Once the key is in place, pushing a first commit to GitHub is the natural next move.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.