GitHub SSH Key: Set Up Password-Free Git Push and Pull
If you have ever been prompted for a username and a personal access token every time you push to GitHub, you already know the friction a GitHub SSH key removes. Set up the key once, and every `git clone`, `git pull`, and `git push` afterward authenticates silently over an encrypted SSH connection — no passwords, no tokens, no prompts.
This is a developer-to-developer walkthrough. We will check for existing keys, generate a modern Ed25519 key, load it into the SSH agent, register the public half with GitHub, test the handshake, and switch your repositories to SSH remotes. We will also cover the HTTPS-versus-SSH tradeoff, the dreaded `Permission denied (publickey)` error, and how to juggle multiple GitHub accounts on one machine.
Key Takeaways
• An SSH key lets Git authenticate to GitHub without passwords or tokens — set it up once, push forever.
• Generate a key with `ssh-keygen -t ed25519 -C “[email protected]”`, then add the public key (`.pub`) to GitHub.
• The private key never leaves your machine; only the public key is pasted into GitHub.
• Load the key into `ssh-agent` so Git can use it: `eval “$(ssh-agent -s)”` then `ssh-add`.
• `Permission denied (publickey)` almost always means the key isn’t loaded in the agent, or you pasted the wrong key into GitHub.
Why use an SSH key with GitHub instead of HTTPS?
GitHub supports two transport protocols for Git: HTTPS and SSH. Both move the same commits; the difference is how you prove who you are.
With HTTPS, GitHub dropped password authentication years ago, so every operation now requires a personal access token (PAT) in place of a password. You either type that token on each `git push`, or you store it in a credential helper that you have to rotate when the token expires.
With SSH, authentication is handled by a cryptographic key pair. You generate two linked files: a private key that stays on your machine and a public key you hand to GitHub. When Git connects, the two halves perform a challenge-response handshake. No secret is ever transmitted, and you never type anything.
For any machine you control and use regularly — your laptop, a build server, a VPS that deploys code — SSH is the practical winner. The setup below takes about three minutes and pays you back on every Git operation for the life of the machine. If you are still getting comfortable with the underlying tooling, the guide is a good companion read.
How do I check for existing SSH keys?
Before generating a new key, check whether one already exists. Reusing a working key is fine; you do not need a separate key per service.
“`bash ls -al ~/.ssh “`
You are looking for a pair of files with matching names, one ending in `.pub`:
“`text id_ed25519 # private key — keep this secret id_ed25519.pub # public key — this goes on GitHub “`
Older setups may show `id_rsa` and `id_rsa.pub` instead. If you see a `.pub` file you recognize, skip to the step where we copy it to GitHub. If `~/.ssh` does not exist or is empty, generate a fresh key.
How do I generate a GitHub SSH key?
Use Ed25519 — it is faster and more secure than the older RSA default, and GitHub fully supports it.
“`bash ssh-keygen -t ed25519 -C “[email protected]” “`
You will be prompted three times:
“`text Enter file in which to save the key (/home/you/.ssh/id_ed25519): [press Enter] Enter passphrase (empty for no passphrase): [type a passphrase or press Enter] Enter same passphrase again: [confirm] “`
Press Enter to accept the default location. A passphrase is optional but recommended on shared or portable machines — it encrypts the private key at rest. If you set one, the `ssh-agent` step below will cache it so you only type it once per session.
If your environment predates Ed25519 support (very old systems), fall back to RSA with a strong key size:
“`bash ssh-keygen -t rsa -b 4096 -C “[email protected]” “`
The full mechanics of key generation, including hardware-backed keys, are covered in the guide.
How do I add the key to the ssh-agent?
The `ssh-agent` is a background process that holds your decrypted private key in memory so Git does not have to ask for your passphrase on every command. Start it, then add your key.
“`bash
eval “$(ssh-agent -s)”
ssh-add ~/.ssh/id_ed25519
“`
On macOS, store the passphrase in the Keychain so it persists across reboots:
“`bash ssh-add –apple-use-keychain ~/.ssh/id_ed25519 “`
On Windows, the agent ships with Git for Windows and OpenSSH. In PowerShell:
“`powershell Start-Service ssh-agent ssh-add $env:USERPROFILE\.ssh\id_ed25519 “`
How do I copy the public key?
You need to copy the public key — the `.pub` file — to your clipboard. Never copy or share the private key.
“`bash
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
pbcopy < ~/.ssh/id_ed25519.pub
clip < ~/.ssh/id_ed25519.pub ```
If you do not have a clipboard utility, just print it and copy by hand:
“`bash cat ~/.ssh/id_ed25519.pub “`
The output is a single line that looks like this:
“`text ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI…rest-of-key… [email protected] “`
Copy the entire line, including the `ssh-ed25519` prefix and the trailing comment.
How do I add the SSH key to GitHub?
Now register the public key with your GitHub account:
- Sign in to GitHub and open Settings (top-right profile menu).
- In the left sidebar, click SSH and GPG keys.
- Click New SSH key.
- Give it a descriptive Title — for example, `work-laptop` or `deploy-server-vps`.
- Leave Key type as Authentication Key.
- Paste the public key into the Key field.
- Click Add SSH key.
A clear title matters once you have keys from several machines: when you retire a laptop, you want to know exactly which key to revoke.
How do I test the GitHub SSH connection?
Verify the handshake before relying on it:
“`bash ssh -T [email protected] “`
The first connection asks you to trust GitHub’s host fingerprint — type `yes`:
“`text The authenticity of host ‘github.com (140.82.x.x)’ can’t be established. ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU. Are you sure you want to continue connecting (yes/no)? yes “`
A successful test returns:
“`text Hi yourusername! You’ve successfully authenticated, but GitHub does not provide shell access. “`
That “does not provide shell access” line is expected and correct — GitHub uses SSH only for Git, not for an interactive shell. If you see `Permission denied (publickey)` instead, jump to the troubleshooting section below.
How do I use SSH URLs for clone and remotes?
With the key working, point Git at the SSH endpoint. For a fresh clone, use the SSH URL:
“`bash git clone [email protected]:username/repository.git “`
Note the format: `[email protected]:user/repo.git`, with a colon before the path — not a slash. GitHub’s SSH URL always starts with `[email protected]:`. For more on the cloning workflow itself, see the guide.
For a repository you already cloned over HTTPS, switch the remote in place instead of re-cloning:
“`bash
git remote -v
git remote set-url origin [email protected]:username/repository.git
git remote -v
“`
From here, `git push` and `git pull` run without a single prompt.
The SSH-versus-HTTPS choice for GitHub is really a question about where you authenticate from and how often. HTTPS makes you supply credentials — now a personal access token, since passwords were dropped — on every operation, or through a credential helper you have to maintain. SSH authenticates with a key you set up once, so every push, pull, and clone afterward is silent. For a machine you control and use regularly — your dev box, or a server that deploys — SSH keys are the clear win: set the key up once, and Git just works forever with no prompts and no tokens to rotate. The corollary that trips people up is directional: the public key goes on GitHub, the private key stays on your machine. And `Permission denied (publickey)` almost always means the key isn’t loaded in your `ssh-agent`, or you added the wrong key — the private one instead of the public one — to GitHub. One-time setup, a lifetime of frictionless Git.
HTTPS vs SSH for GitHub: which should you use?
| Factor | HTTPS | SSH |
|---|---|---|
| Credential per operation | Personal access token (or credential helper) | None after one-time key setup |
| Initial setup effort | Minimal | A few minutes (generate + register key) |
| Best for | One-off clones, locked-down networks | Daily-driver machines, deploy servers |
| What you store | Token in a credential manager | Private key in `~/.ssh` |
| Firewall friendliness | Port 443, rarely blocked | Port 22, sometimes blocked on restricted networks |
| Token/key expiry | Tokens expire and need rotation | Key persists until you revoke it |
If you work on a network that blocks port 22, GitHub also offers SSH over the HTTPS port (`ssh.github.com` on 443) — but for most setups, the standard SSH endpoint is all you need.
How do I fix “Permission denied (publickey)”?
This is the most common SSH error, and it has three usual causes. Work through them in order.
1. The key isn’t loaded in the agent. List the identities the agent currently holds:
“`bash ssh-add -l “`
If it prints `The agent has no identities`, re-add your key:
“`bash eval “$(ssh-agent -s)” ssh-add ~/.ssh/id_ed25519 “`
2. The agent isn’t running, or you are in a fresh shell. The `eval “$(ssh-agent -s)”` line only affects the current shell session. If you opened a new terminal, the agent reference is gone. Re-run it, or add the startup lines to your `~/.bashrc` or `~/.zshrc`.
3. The wrong key — or no matching key — is on GitHub. Run the connection in verbose mode to see which key SSH is offering:
“`bash ssh -vT [email protected] “`
Look for lines like `Offering public key:` and confirm SSH is presenting the key whose `.pub` you pasted into GitHub. A classic mistake is pasting the private key (the file with no extension) into GitHub instead of the `.pub` file — GitHub only ever wants the public key. If in doubt, re-copy `~/.ssh/id_ed25519.pub` and re-add it. The broader mechanics of how key pairs authenticate are covered in the guide.
Built for Git-based workflows: DarazHost. DarazHost VPS and dedicated servers are ideal for Git deployment. Generate an SSH key directly on your server, add it to GitHub, and clone, pull, and deploy your repositories securely without passwords — all with full root access and 24/7 support. It is the real, controlled environment serious Git deployment needs, with no shared-host restrictions getting in your way.
How do I use multiple GitHub accounts on one machine?
If you push to both a work account and a personal account from the same machine, you cannot use one key for both — GitHub ties each key to a single account. The fix is an `~/.ssh/config` file that maps a host alias to a specific key.
First, generate a second key with a distinct filename:
“`bash ssh-keygen -t ed25519 -C “[email protected]” -f ~/.ssh/id_ed25519_work “`
Then create or edit `~/.ssh/config`:
“`text
Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes
Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes “`
Add the work key’s `.pub` to the work GitHub account, then clone work repos using the alias as the host:
“`bash
git clone [email protected]:personal-user/repo.git
git clone git@github-work:work-org/repo.git “`
The `IdentitiesOnly yes` line is important: it forces SSH to use exactly the key named in `IdentityFile` rather than offering every loaded key, which prevents GitHub from rejecting the connection after too many wrong-key attempts.
For the bigger picture on running Git on infrastructure you actually control — servers, deploy pipelines, and the environments where SSH keys earn their keep — see our pillar guide: hosting for developers: the complete guide to a real environment you control.
Frequently asked questions
Is the GitHub SSH key the public key or the private key? You add the public key (the file ending in `.pub`) to GitHub. The private key — the file with no extension — stays on your machine and is never shared. The pair work together: GitHub holds the public half, your machine keeps the private half, and the two perform a handshake without transmitting any secret.
Do I need a new SSH key for every repository? No. One key authenticates you to your entire GitHub account and every repository you have access to. You only need additional keys when you use multiple GitHub accounts on the same machine, in which case you separate them with an `~/.ssh/config` file.
Why does `ssh -T [email protected]` say “does not provide shell access”? That message is the success case. GitHub accepts SSH connections only for Git operations, not for an interactive login shell. Seeing `Hi username! You’ve successfully authenticated` means your key works.
Can I switch an existing HTTPS repository to SSH without re-cloning? Yes. Run `git remote set-url origin [email protected]:username/repository.git` inside the repo. This rewrites the remote URL in place; your local commits and branches are untouched.
Should I set a passphrase on my SSH key? On a personal machine you control, a passphrase is optional but adds a layer of protection if the device is lost or stolen. The `ssh-agent` caches it so you only type it once per session. On an unattended deploy server, many teams use a passphrase-free key combined with strict file permissions and limited access.