TL;DR

StepCommand / Action
Check existing keysls ~/.ssh/
Generate new keyssh-keygen -t ed25519 -C "[email protected]"
Start SSH agenteval "$(ssh-agent -s)"
Add key to agentssh-add ~/.ssh/id_ed25519
Copy public keycat ~/.ssh/id_ed25519.pub
Upload to platformsGitHub → GitLab → Bitbucket settings
Test connectionsssh -T [email protected]
Multiple accountsCreate ~/.ssh/config with host aliases

Tested on: Ubuntu 22.04, macOS Ventura, Windows 11 (Git Bash and WSL2)


What Are SSH Keys and Why Use Them?

SSH keys are a pair of cryptographic files: a private key (stays on your machine) and a public key (uploaded to the platform). When you connect, the platform checks that your private key matches the public key on file — no password required.

Compared to HTTPS with a personal access token, SSH keys are:

Ed25519 vs RSA

Ed25519RSA
Recommended✅ Yes⚠️ Legacy only
Key sizeShort (68 chars)Long (3000+ chars)
SpeedFasterSlower
CompatibilityModern systemsOlder enterprise servers

Use Ed25519 unless you are connecting to a legacy system that does not support it.


Step 1: Check for Existing SSH Keys

Before generating anything, check whether you already have a key pair:

1
ls ~/.ssh/

If you see any of the following, you already have keys:

You can reuse an existing key rather than generating a new one. If the ~/.ssh/ directory does not exist or is empty, move on to Step 2.

When to generate fresh: If your existing key has no passphrase, or was created with RSA at under 4096 bits, generate a new Ed25519 key.


Step 2: Generate a New SSH Key Pair

Run the following command, replacing the email with the one tied to your Git accounts:

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

You will be prompted twice:

1. File location Press Enter to accept the default (~/.ssh/id_ed25519). If you need separate keys per account, give it a distinct name here instead:

~/.ssh/id_ed25519_github

2. Passphrase Set one. A passphrase protects your private key so that even if someone gets the file, they cannot use it. The SSH agent (Step 3) means you only type it once per session.

After running the command, two files are created:

FilePurpose
~/.ssh/id_ed25519Private key — never share this
~/.ssh/id_ed25519.pubPublic key — upload this to platforms

Step 3: Add Your Key to the SSH Agent

The SSH agent holds your decrypted private key in memory so you do not re-enter your passphrase on every Git operation.

Start the agent

1
eval "$(ssh-agent -s)"

Add your private key

1
ssh-add ~/.ssh/id_ed25519

You will be asked for your passphrase once. After that, the agent handles authentication silently.

Make it persistent across sessions

macOS — add to ~/.zshrc or ~/.bash_profile:

1
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Then add to ~/.ssh/config:

Host *
  AddKeysToAgent yes
  UseKeychain yes

Linux — add to ~/.bashrc:

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

Windows (Git Bash or WSL2) — add to ~/.bashrc:

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

Step 4: Add Your Public Key to Each Platform

First, copy your public key:

1
cat ~/.ssh/id_ed25519.pub

Select and copy the entire output. It starts with ssh-ed25519 and ends with your email.

GitHub

  1. Go to github.com → Settings → SSH and GPG keys
  2. Click New SSH key
  3. Give it a recognizable title (e.g., Work MacBook 2025)
  4. Paste your public key
  5. Click Add SSH key

[PLACEHOLDER: Screenshot showing the GitHub SSH key settings page with the “New SSH key” button highlighted]

GitLab

  1. Go to gitlab.com → User menu (top right) → Preferences → SSH Keys
  2. Paste your public key in the Key field
  3. Add a title and optionally an expiration date
  4. Click Add key

GitLab lets you set an expiration date on keys, which is useful for security audits. GitHub does not have this option for personal SSH keys.

Bitbucket

  1. Go to bitbucket.org → Personal settings → SSH keys
  2. Click Add key
  3. Add a label and paste your public key
  4. Click Add key

Bitbucket also supports workspace-level SSH keys for CI/CD pipelines. The above covers your personal account only.


Step 5: Test Your SSH Connection

Test each platform individually. You do not need to be inside a repository.

GitHub:

Expected: Hi username! You've successfully authenticated...

GitLab:

Expected: Welcome to GitLab, @username!

Bitbucket:

Expected: logged in as username.

If you see Permission denied (publickey), jump to the Troubleshooting section below.


Managing Multiple SSH Keys

This is where most guides stop — and where most people run into problems.

If you have two GitHub accounts (personal and work), or use all three platforms, you need to tell SSH which key to use for which host.

Generate separate keys per account

1
2
3
4
5
ssh-keygen -t ed25519 -C "[email protected]"
# Save as: ~/.ssh/id_ed25519_github_personal

ssh-keygen -t ed25519 -C "[email protected]"
# Save as: ~/.ssh/id_ed25519_github_work

Add all keys to the agent:

1
2
ssh-add ~/.ssh/id_ed25519_github_personal
ssh-add ~/.ssh/id_ed25519_github_work

Create the SSH config file

Create or edit ~/.ssh/config:

# Personal GitHub
Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github_personal

# Work GitHub
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github_work

# GitLab
Host gitlab.com
  HostName gitlab.com
  User git
  IdentityFile ~/.ssh/id_ed25519_gitlab

# Bitbucket
Host bitbucket.org
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/id_ed25519_bitbucket

Update your remote URLs

Use the host alias instead of github.com when setting or updating remotes:

1
2
# Instead of: [email protected]:username/repo.git
git remote set-url origin git@github-personal:username/repo.git

Test the aliases

1
2
ssh -T git@github-personal
ssh -T git@github-work

[PLACEHOLDER: Diagram showing how the SSH config file maps host aliases to different keys and platforms]


Troubleshooting

Permission denied (publickey)

Agent not running

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

On Windows, make sure you are using Git Bash or WSL — not the standard Windows Command Prompt.

Wrong key being used

Check your ~/.ssh/config file. Use ssh -vT [email protected] and look for the IdentityFile line in the output to see which key is being attempted.

Key not accepted after adding

It can take a few seconds for the platform to register a newly added key. Wait 30 seconds and try again. Also confirm you copied from the .pub file, not the private key.

Bad file permissions

SSH is strict about file permissions. Fix them with:

1
2
3
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Keeping Your Keys Secure


FAQ

Can I use the same SSH key for GitHub, GitLab, and Bitbucket?

Yes. One key pair works across all three. Upload the same id_ed25519.pub to each platform. Use separate keys only if you want to revoke access per platform without affecting others, or for security auditing purposes.

Does my SSH key expire?

On GitHub and Bitbucket, personal SSH keys do not expire by default. GitLab lets you set an optional expiration date. Leave the expiration field blank on GitLab and the key will not expire.

What is the difference between Ed25519 and RSA?

Ed25519 uses elliptic curve cryptography and produces smaller, faster keys. It offers stronger security than a 2048-bit RSA key. Use Ed25519 unless a system specifically requires RSA.

I already have an RSA key. Do I need to switch?

Not immediately. A 4096-bit RSA key is still acceptable. If yours is 2048 bits or smaller, generate a new Ed25519 key and replace it.

What happens if I lose my private key?

Generate a new key pair, upload the new public key to each platform, and remove the old one from your account settings. Your repositories are not affected since the key only controls authentication.

Can SSH keys be used for GitHub Actions or Bitbucket Pipelines?

Not in the same way. CI systems use deploy keys (repository-specific SSH keys) or access tokens, not your personal SSH key. Deploy keys are set up separately under repository settings.

Do SSH keys work with Git on Windows without WSL?

Yes, through Git Bash (included with Git for Windows). It ships with OpenSSH, and all commands in this guide work without modification. The ~ path maps to C:\Users\yourname.