SSH keys use asymmetric encryption to enable passwordless login and identity verification — more secure and convenient than passwords. This guide covers the most common scenarios in day-to-day development.
Choosing an Algorithm
Pick your algorithm before generating a key.
| Algorithm | Recommendation | Notes |
|---|---|---|
| Ed25519 | ✅ First choice | Modern elliptic-curve, short key, fast, strong security |
| RSA 4096 | ✅ For compatibility | Best compatibility, required for legacy systems, longer key |
| ECDSA | ⚠️ Usable | Shorter than RSA, but some implementations have weaknesses |
| RSA 2048 | ❌ Not recommended | Considered insufficient strength today |
| DSA | ❌ Not recommended | Deprecated |
Bottom line: use Ed25519 for new setups; fall back to RSA 4096 only for legacy system compatibility.
Basics: Generating Your First SSH Key
Ed25519 (recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"
RSA 4096 (for compatibility)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
You will be prompted:
Enter file in which to save the key (/Users/you/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
- File path: press Enter to accept the default
- Passphrase: recommended — it adds a password layer on top of the private key
After generation:
~/.ssh/id_ed25519— private key, never share or upload this~/.ssh/id_ed25519.pub— public key, paste this into platforms
Viewing the Public Key
cat ~/.ssh/id_ed25519.pub
Output looks like:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... your_email@example.com
Copy this entire line and paste it into GitHub / GitLab / server authorized_keys.
Scenario 1: Multiple Platforms and Accounts (Most Common)
It is very common to juggle a personal GitHub account, a work GitHub account, GitLab, and internal servers at the same time — each needing its own key.
Step 1: Generate separate keys with distinct names
# Personal GitHub
ssh-keygen -t ed25519 -C "me@personal.com" -f ~/.ssh/id_ed25519_github_personal
# Work GitHub
ssh-keygen -t ed25519 -C "me@work.com" -f ~/.ssh/id_ed25519_github_work
# GitLab
ssh-keygen -t ed25519 -C "me@work.com" -f ~/.ssh/id_ed25519_gitlab
# Internal server
ssh-keygen -t ed25519 -C "server" -f ~/.ssh/id_ed25519_server
Step 2: Configure ~/.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
# Internal server
Host dev-server
HostName 192.168.1.100
User ubuntu
Port 22
IdentityFile ~/.ssh/id_ed25519_server
Step 3: Use the aliases
# Clone a personal repo (replace github.com with the Host alias)
git clone git@github-personal:username/repo.git
# Clone a work repo
git clone git@github-work:company/repo.git
# SSH into the server directly
ssh dev-server
Scenario 2: Adding Keys to ssh-agent
If your private key has a passphrase, you would normally type it on every use. ssh-agent remembers the passphrase for the duration of your session.
# Start the agent (usually already running)
eval "$(ssh-agent -s)"
# Add your key
ssh-add ~/.ssh/id_ed25519
# List loaded keys
ssh-add -l
macOS persistent storage (saves the key to Keychain so you do not need to re-add after a reboot):
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
Add these lines to ~/.ssh/config so macOS uses Keychain automatically:
Host *
AddKeysToAgent yes
UseKeychain yes
Scenario 3: Deploying a Public Key to a Server
Option 1: ssh-copy-id (easiest)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip
Option 2: Pipe it over
cat ~/.ssh/id_ed25519.pub | ssh user@server_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Option 3: Edit on the server directly
After logging in:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "paste your public key here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Permissions matter — SSH will refuse keys if they are wrong:
| Path | Permission |
|---|---|
~/.ssh/ | 700 |
~/.ssh/authorized_keys | 600 |
| Private key file | 600 |
| Public key file | 644 |
Scenario 4: Windows
Windows has a few different setups to handle.
Git Bash / WSL
The flow is essentially the same as macOS/Linux. The ~/.ssh/ path works the same way.
PowerShell (built-in OpenSSH)
Windows 10 1809+ ships with OpenSSH:
# Generate a key
ssh-keygen -t ed25519 -C "your_email@example.com"
# Keys are stored at:
# C:\Users\YourName\.ssh\id_ed25519
Enable the ssh-agent service
# Run as Administrator
Set-Service -Name ssh-agent -StartupType Automatic
Start-Service ssh-agent
# Add your key
ssh-add $env:USERPROFILE\.ssh\id_ed25519
Scenario 5: Testing the Connection
Verify everything works after setup:
# Test GitHub
ssh -T git@github.com
# Output: Hi username! You've successfully authenticated...
# Test with an alias
ssh -T git@github-personal
# Test a server (-v shows verbose logs for troubleshooting)
ssh -v user@server_ip
Scenario 6: Rotating or Revoking a Key
After generating a new key, you need to:
- Add the new public key to all platforms and servers
- Remove the old public key from each platform and server
- Optionally delete the old private key file locally
# Remove the old key from ssh-agent
ssh-add -d ~/.ssh/old_key
# Delete the old key files
rm ~/.ssh/old_key ~/.ssh/old_key.pub
Remove an old key from a server:
# Edit authorized_keys and delete the corresponding line
nano ~/.ssh/authorized_keys
Common Issues
Permission denied (publickey)
- Verify the public key is added to the target platform
- Check that
~/.ssh/authorized_keyshas permission600 - Run
ssh -vto inspect the handshake in detail
Passphrase required every time
- Add the key to ssh-agent:
ssh-add ~/.ssh/id_ed25519 - On macOS, use
--apple-use-keychainto persist it
Which key is git using?
# Check which identity is active
ssh -T git@github.com
# Test a specific key
ssh -i ~/.ssh/id_ed25519_github_personal -T git@github.com
Fonnpo