If you've ever set up SSH access to a Linux server, you already know 90% of what's needed to connect to GitHub and GitLab. Run ssh-keygen, keep the private key on your machine, drop the public key somewhere the remote side trusts. GitHub and GitLab aren't doing anything exotic here — they're just remote machines that take your public key through a web form instead of ~/.ssh/authorized_keys.

Short version: generate a key pair → private key stays local → public key gets pasted into GitHub/GitLab settings → clone and push over SSH without typing a password.


Quick Recap: What ssh-keygen Actually Does

ssh-keygen -t ed25519 -C "[email protected]"

This produces two files:

File What it is Where it goes
~/.ssh/id_ed25519 Private key Never leaves your machine
~/.ssh/id_ed25519.pub Public key Copied to whatever you want to reach

On a plain Linux server, "copied to the server" means appending the .pub file's contents to ~/.ssh/authorized_keys on the remote host. Under the hood, SSH authentication is challenge-response with asymmetric crypto: the server encrypts random data with your public key, only your private key can decrypt it, and the server checks the proof. No password ever crosses the wire.

That entire model carries over to GitHub and GitLab unchanged.


The Mapping: Server Setup vs GitHub/GitLab Setup

Step Linux server GitHub / GitLab
Generate key ssh-keygen -t ed25519 Same command
Public key destination ~/.ssh/authorized_keys on server Web UI: Settings → SSH Keys
Private key usage Local SSH client Local SSH client (same files)
Connection test ssh user@server ssh -T [email protected] / ssh -T [email protected]
Git remote URL ssh://user@server/repo.git [email protected]:owner/repo.git

One real difference: you never get a shell on github.com or gitlab.com. SSH there only authenticates you for Git operations (clone, push, pull) and, optionally, commit signing.


GitHub Workflow

1. Generate the key

ssh-keygen -t ed25519 -C "[email protected]"

Ed25519 is the recommended default — smaller keys, faster signing, no known weaknesses. If you're stuck on a legacy system without Ed25519 support, fall back to ssh-keygen -t rsa -b 4096 -C "[email protected]".

Worth knowing if you're troubleshooting an old key: GitHub permanently dropped support for DSA keys on March 15, 2022, and any RSA key generated after November 2, 2021 must use a SHA-2 signature algorithm (older RSA keys grandfathered in before that date can still use SHA-1). If you're generating a key today this doesn't change anything — Ed25519 or RSA 4096 both work fine — but it explains why a decade-old RSA key might suddenly stop authenticating.

2. Load into ssh-agent (optional but recommended)

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

The agent holds your key in memory and remembers the passphrase, so you type it once per boot instead of once per git push.

In ~/.ssh/config, macOS users should add Keychain integration:

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

3. Copy the public key to GitHub

cat ~/.ssh/id_ed25519.pub | clip        # Windows Git Bash
xclip -sel clip < ~/.ssh/id_ed25519.pub # Linux
pbcopy < ~/.ssh/id_ed25519.pub          # macOS

Then: GitHub → Settings → SSH and GPG keys → New SSH key → paste → give it a title you'll actually recognize later ("Work Laptop", "Home Desktop") → Save.

4. Test the connection

ssh -T [email protected]

A working setup looks like:

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

On first connection you may be asked to verify a host key fingerprint — check it against GitHub's published fingerprints before answering yes.

5. Clone over SSH

git clone [email protected]:owner/repo.git

The [email protected]: prefix is the tell that you're on SSH. HTTPS remotes (https://github.com/...) authenticate with tokens instead, which is a different setup entirely.


GitLab: Same Dance, Extra Knobs

The core steps are identical — ssh-keygen, ssh-add, paste the public key under your avatar → Edit profile → SSH keys, then test with:

ssh -T [email protected]
# self-managed instance: ssh -T [email protected]

GitLab exposes a few controls GitHub doesn't surface the same way:

Feature GitLab behavior
Key expiration Optional expiry date on each key; GitLab emails a warning 7 days before expiry and again on the expiry day
Usage type Per-key: Authentication, Signing, or Authentication & Signing
Revoke vs Delete Revoke is only available on keys with the Signing or Authentication & Signing usage type — it's built for pulling a compromised signing key without losing the audit trail. Authentication-only keys don't get a Revoke option; you just Delete them
Compromised key blocklist Every new key you add is checked against a list of known-leaked keys and rejected if it matches

One account-level key covers every project you have access to — you don't need a separate key per repo unless you specifically want that separation (for example, different keys per client org).


Security Rules That Apply Identically

  • Private key never gets uploaded, anywhere. If you're about to paste something into a web form and it starts with -----BEGIN OPENSSH PRIVATE KEY-----, stop. That's the file without .pub. Only the public key is meant to be shared — that's the entire point of asymmetric crypto.
  • Use a passphrase. Combined with ssh-agent, the actual cost to you is one prompt per boot, not one per push.
  • Review your keys periodically. GitHub auto-deletes keys that haven't been used in a year. GitLab shows a last-used date per key. Either way, clean out entries from laptops you no longer own.
  • Different keys per device. If one laptop gets compromised, you revoke or delete that one key and every other device keeps working. Managing multiple keys is a ~/.ssh/config entry away:
Host github.com
  IdentityFile ~/.ssh/id_ed25519_work

Host gitlab.com
  IdentityFile ~/.ssh/id_ed25519_gitlab
  • SSO adds an extra step (GitHub Enterprise). Orgs enforcing SAML SSO require you to separately authorize each SSH key for that org after adding it to your account — the key being present on your account isn't enough on its own.

Troubleshooting

Symptom Likely cause Fix
Permission denied (publickey) Public key not actually on the account, or agent isn't loaded Re-check the paste, run ssh-add -l to list what the agent currently holds
Wrong identity accepted or rejected Multiple keys, agent is offering the wrong one Pin the key with IdentityFile in ~/.ssh/config
Host key verification failed Host fingerprint changed, or a typo Verify the fingerprint against official docs, then update ~/.ssh/known_hosts
Prompted for passphrase on every push ssh-agent isn't running, or the key was never added to it eval "$(ssh-agent -s)" then ssh-add
Works in terminal, fails in a Git GUI GUI is using a different (or no) ssh-agent Point the GUI at your system OpenSSH agent
Git still asks for a password despite SSH setup Remote URL is still HTTPS git remote set-url origin [email protected]:owner/repo.git

Bottom Line

Nothing about GitHub or GitLab SSH is new cryptography. ssh-keygen still makes a private/public pair, the private key still never leaves your machine, and the public key still lands on the remote side — it just happens that the remote side is a paste box in a web settings page instead of authorized_keys. If you already understood the Linux server flow, you understood this one before you clicked the link.


Sources: GitHub Docs — Connecting to GitHub with SSH, GitHub Docs — Deleted or missing SSH keys, GitLab Docs — Use SSH keys with GitLab.