SSH Key Management and Configuration — From Key Generation to Multi-Account Setup

What Is SSH Key Authentication?

SSH (Secure Shell) keys use public-private key pairs instead of passwords for authentication. Using a bank vault analogy, a password is like a number combination (anyone can try), while an SSH key is like a physical key (only the holder can open it).

Auth MethodSecurity LevelConvenienceAutomation
PasswordLow (guessable/stealable)Enter every timeDifficult
SSH KeyHigh (requires private key)Set up onceEasy
SSH Key + PassphraseVery highManaged via ssh-agentEasy

SSH Key Generation

# Generate Ed25519 key (currently recommended algorithm)
ssh-keygen -t ed25519 -C "your.email@example.com"
# Output:
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):       ← Setting a passphrase is recommended
# Enter same passphrase again:
# Your identification has been saved in /home/user/.ssh/id_ed25519
# Your public key has been saved in /home/user/.ssh/id_ed25519.pub

# Use RSA for legacy systems that don't support Ed25519
ssh-keygen -t rsa -b 4096 -C "your.email@example.com"

# Generate keys with specific names (for multi-account setups)
ssh-keygen -t ed25519 -C "work@company.com" -f ~/.ssh/id_ed25519_work
ssh-keygen -t ed25519 -C "personal@gmail.com" -f ~/.ssh/id_ed25519_personal

Checking Key Files

# Check generated key files
ls -la ~/.ssh/
# -rw-------  id_ed25519          ← Private key (never share this!)
# -rw-r--r--  id_ed25519.pub      ← Public key (register on servers)

# View public key contents (register this value on GitHub/servers)
cat ~/.ssh/id_ed25519.pub
# Output: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGx... your.email@example.com

# Check key fingerprint
ssh-keygen -l -f ~/.ssh/id_ed25519.pub
# Output: 256 SHA256:abc123def456... your.email@example.com (ED25519)

ssh-agent: Passphrase Management

When you set a passphrase, you’d have to enter it every time. With ssh-agent, you only need to enter it once per session.

# Start ssh-agent
eval "$(ssh-agent -s)"
# Output: Agent pid 12345

# Add key to agent (enter passphrase once)
ssh-add ~/.ssh/id_ed25519
# Output: Identity added: /home/user/.ssh/id_ed25519 (your.email@example.com)

# List registered keys
ssh-add -l
# Output: 256 SHA256:abc123... your.email@example.com (ED25519)

# On macOS, you can save the passphrase to keychain
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# Remove all keys
ssh-add -D

Auto-Start Configuration (bashrc/zshrc)

# Add to ~/.bashrc or ~/.zshrc
# Start ssh-agent if not already running
if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)" > /dev/null 2>&1
    ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi

Registering SSH Keys on GitHub

# 1. Copy public key
# Linux
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard

# macOS
pbcopy < ~/.ssh/id_ed25519.pub

# Windows (Git Bash)
cat ~/.ssh/id_ed25519.pub | clip

# 2. Register on GitHub
# GitHub → Settings → SSH and GPG keys → New SSH key
# Title: an identifiable name like "My Laptop"
# Key: paste the copied public key

# 3. Test connection
ssh -T git@github.com
# Output: Hi username! You've been authenticated, but GitHub does not provide shell access.

# 4. Change existing HTTPS repository to SSH
git remote set-url origin git@github.com:username/repo.git
git remote -v
# Output: origin  git@github.com:username/repo.git (fetch)
#         origin  git@github.com:username/repo.git (push)

SSH Config File: Managing Connection Settings

The ~/.ssh/config file lets you manage per-host settings, replacing long commands with short aliases.

# ~/.ssh/config

# Default settings (applied to all hosts)
Host *
    AddKeysToAgent yes           # Automatically add keys to agent
    IdentitiesOnly yes           # Only try specified keys
    ServerAliveInterval 60       # Send keepalive every 60 seconds (prevent disconnection)
    ServerAliveCountMax 3        # Disconnect after 3 failed keepalives

# GitHub personal account
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal

# GitHub work account (using alias)
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work

# GitLab
Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_ed25519
    PreferredAuthentications publickey

# Dev server (quick access via alias)
Host dev-server
    HostName 192.168.1.100
    User deploy
    Port 2222                    # Custom port instead of default 22
    IdentityFile ~/.ssh/id_ed25519_server

# Production server (via jump host)
Host prod-server
    HostName 10.0.0.50
    User deploy
    ProxyJump bastion-server     # Connect through bastion

Host bastion-server
    HostName bastion.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519_bastion
# Usage examples after applying config

# Quick access via alias (instead of: ssh -i ~/.ssh/id_ed25519_server -p 2222 deploy@192.168.1.100)
ssh dev-server

# Production server access (automatic bastion routing)
ssh prod-server

# SCP file transfer also uses aliases
scp ./deploy.tar.gz dev-server:/tmp/

# Port forwarding (local 3000 → server 3000)
ssh -L 3000:localhost:3000 dev-server

GitHub/GitLab Multi-Account Setup

For when you need to use personal and work GitHub accounts simultaneously.

# 1. Generate keys per account
ssh-keygen -t ed25519 -C "personal@gmail.com" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work@company.com" -f ~/.ssh/id_ed25519_work

# 2. Register each public key on the corresponding GitHub account
# personal public key → personal GitHub
# work public key → work GitHub

# 3. Configure ~/.ssh/config (see example above)
# Host github.com → personal key
# Host github-work → work key

# 4. Per-repository Git configuration
# Personal repository
cd ~/personal/my-project
git remote set-url origin git@github.com:personal-user/my-project.git
git config user.name "Personal Name"
git config user.email "personal@gmail.com"

# Work repository (using alias!)
cd ~/work/company-project
git remote set-url origin git@github-work:company-org/company-project.git
#                         ↑ Using github-work alias (not github.com)
git config user.name "Work Name"
git config user.email "work@company.com"

# 5. Test
ssh -T git@github.com          # Verify personal account
ssh -T git@github-work         # Verify work account

Automate with gitconfig Conditional Includes

# ~/.gitconfig (global settings)
[user]
    name = Personal Name
    email = personal@gmail.com

# Automatically apply work settings in the work directory
[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work
# ~/.gitconfig-work (work-specific settings)
[user]
    name = Work Name
    email = work@company.com

Security Recommendations

ItemRecommended SettingRisk
AlgorithmEd25519RSA under 2048 bits is vulnerable
PassphraseRequiredWithout it, a stolen key file is immediately usable
Private key permissionschmod 600 (owner-only read)SSH refuses keys readable by others
Config permissionschmod 644Overly open permissions are a security risk
Key separationSeparate keys per purpose/serverIf one key is compromised, everything is exposed
Key rotationRecommended yearlyOld keys carry risk of undetected compromise
# Set file permissions correctly
chmod 700 ~/.ssh               # .ssh directory
chmod 600 ~/.ssh/id_ed25519    # Private key (owner read/write only)
chmod 644 ~/.ssh/id_ed25519.pub # Public key (read allowed)
chmod 644 ~/.ssh/config        # Config file
chmod 644 ~/.ssh/known_hosts   # known_hosts

Practical Tips

  • Use Ed25519 as the default: It provides stronger security with shorter keys than RSA, and better performance too.
  • Always set a passphrase: Even if your laptop is lost or key files are leaked, a passphrase prevents immediate exploitation.
  • Separate keys by purpose: Create separate keys for GitHub, server access, and work/personal use. If one is exposed, the damage is limited.
  • Make full use of ~/.ssh/config: Replacing complex ssh commands with short aliases dramatically improves productivity.
  • Manage known_hosts: Always verify the fingerprint of a server you’re connecting to for the first time. When a server changes, remove the old entry with ssh-keygen -R hostname.
  • Use Deploy Keys for GitHub: In CI/CD, use Deploy Keys that access only specific repositories instead of full account keys to reduce the security scope.

Was this article helpful?