Skip to content

Instantly share code, notes, and snippets.

@coltenkrauter
Last active September 18, 2025 04:12
Show Gist options
  • Select an option

  • Save coltenkrauter/da470bdccd3bb558f1c9c30b5dcf3a0f to your computer and use it in GitHub Desktop.

Select an option

Save coltenkrauter/da470bdccd3bb558f1c9c30b5dcf3a0f to your computer and use it in GitHub Desktop.
SSH with 2 GitHub accounts on github.com - Complete setup guide with SSH config, shell functions, and examples

Dual GitHub SSH Setup: Personal & Work Accounts

A clean, secure guide for using two different GitHub accounts on the same machine with automatic SSH key selection and Git identity management.

Overview

This setup automatically uses the correct GitHub account based on your working directory.

Prerequisites

  • macOS/Linux with SSH and Git installed
  • Two GitHub accounts (personal and work)
  • Basic familiarity with terminal commands

Step 1: Create SSH Keys

Follow GitHub's official SSH setup guide for detailed instructions.

Quick setup:

# Personal GitHub account (Ed25519)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_personal

# Work GitHub account (Ed25519 or FIDO2 hardware token)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_work

Security: Use passphrases for work keys. Consider FIDO2 hardware tokens for maximum security.

Step 2: Secure SSH Directory Permissions

Critical: Lock down your SSH directory and keys:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/config ~/.ssh/id_*

This prevents accidental world-readable keys or configs.

Step 3: Add SSH Keys to GitHub

Get your public keys:

echo "=== Personal GitHub Key ==="
cat ~/.ssh/id_ed25519_github_personal.pub

echo -e "\n=== Work GitHub Key ==="
cat ~/.ssh/id_ed25519_github_work.pub

Add to GitHub:

  1. Go to GitHub.com → Settings → SSH and GPG keys
  2. Click "New SSH key"
  3. Give it a descriptive title (e.g., "Personal MacBook" or "Work MacBook")
  4. Paste the appropriate public key
  5. Click "Add SSH key"
  6. Repeat for the second account

Step 4: Configure SSH Config

Create or edit ~/.ssh/config to add SSH aliases:

# Personal GitHub account (default port 22)
Host github-personal
    HostName github.com
    User git
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519_github_personal
    UseKeychain yes
    AddKeysToAgent yes

# Work GitHub account (default port 22)
Host github-work
    HostName github.com
    User git
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519_github_work
    UseKeychain yes
    AddKeysToAgent yes

# Alternative: If port 22 is blocked, use port 443
Host github-personal-443
    HostName ssh.github.com
    Port 443
    User git
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519_github_personal
    UseKeychain yes
    AddKeysToAgent yes

Host github-work-443
    HostName ssh.github.com
    Port 443
    User git
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519_github_work
    UseKeychain yes
    AddKeysToAgent yes

Key Configuration Explained:

  • IdentitiesOnly yes: Critical! This tells SSH to only use the specified key, not try other keys from the agent first
  • UseKeychain yes: Stores passphrases in macOS Keychain (macOS only - remove on Linux)
  • AddKeysToAgent yes: Adds keys to SSH agent for convenience
  • HostName ssh.github.com: Required for SSH over port 443, not github.com
  • Port 22 vs 443: Use 22 by default; only use 443 if port 22 is blocked

Step 5: Test SSH Connections

Test both connections to ensure they're working:

# Test personal account
ssh -T github-personal
# Should show: Hi [your-personal-username]! You've successfully authenticated...

# Test work account  
ssh -T github-work
# Should show: Hi [your-work-username]! You've successfully authenticated...

Step 6: Configure Git with includeIf and insteadOf

Configure Git to automatically use the correct account and SSH key based on your working directory:

Global Git Config (~/.gitconfig):

[user]
    name = Your Personal Name
    email = [email protected]

[includeIf "gitdir:/path/to/your/work/directory/"]
    path = ~/.gitconfig-work

[url "git@github-personal:"]
    insteadOf = https://github.com/
    insteadOf = [email protected]:

Work-specific Git Config (~/.gitconfig-work):

[user]
    name = Your Work Name
    email = [email protected]

[url "git@github-work:"]
    insteadOf = https://github.com/
    insteadOf = [email protected]:

How it works:

  • includeIf "gitdir:/path/to/work/": Applies work config to any repo under the specified directory
  • insteadOf: Automatically rewrites both HTTPS and SSH URLs to use the correct SSH host
  • Per-directory configs: Ensures correct identity and SSH key for each account
  • SSH URL rewriting: [email protected]: gets rewritten to the appropriate SSH alias

Usage Examples

Automatic URL Rewriting

With the insteadOf configuration, both HTTPS and SSH URLs automatically use the correct SSH key:

# Personal repositories (anywhere outside work directory)
git clone https://github.com/your-personal-username/awesome-project.git
# Automatically becomes: git@github-personal:your-personal-username/awesome-project.git

git clone [email protected]:your-personal-username/awesome-project.git
# Automatically becomes: git@github-personal:your-personal-username/awesome-project.git

# Work repositories (inside work directory)
cd /path/to/your/work/directory/
git clone https://github.com/your-company/company-project.git
# Automatically becomes: git@github-work:your-company/company-project.git

git clone [email protected]:your-company/company-project.git
# Automatically becomes: git@github-work:your-company/company-project.git

Manual SSH Commands (Optional)

If you prefer explicit SSH hosts, you can still use them directly:

# Personal repository
git clone git@github-personal:your-personal-username/repo.git

# Work repository
git clone git@github-work:your-company/repo.git

Test Matrix

Verify your setup works correctly:

# 1. SSH connections
ssh -T github-personal    # Should show personal username
ssh -T github-work        # Should show work username

# 2. Git identity (outside work directory)
git config user.name      # Should show personal name
git config user.email     # Should show personal email

# 3. Git identity (inside work directory)
cd /path/to/your/work/directory/
git config user.name      # Should show work name  
git config user.email     # Should show work email

# 4. URL rewriting (HTTPS)
git clone https://github.com/org/repo.git  # Should use correct SSH host

# 5. URL rewriting (SSH)
git clone [email protected]:org/repo.git      # Should use correct SSH host

# 6. Verify URL rewriting
git remote add origin [email protected]:org/repo.git
git remote -v  # Should show the rewritten SSH alias URL

Key Lifecycle & Security

Key Rotation

  • Work keys: Rotate every 6-12 months
  • Personal keys: Rotate annually or when compromised
  • Process: Generate new key → Add to GitHub → Update SSH config → Remove old key from GitHub

Security Best Practices

  • Passphrases: Use strong passphrases for work keys
  • Hardware tokens: Consider FIDO2 keys for maximum security
  • Access control: Be mindful of which repositories you're accessing with which account
  • Agent forwarding: Avoid forwarding SSH agents to untrusted hosts

Troubleshooting

Both SSH connections show the same username

Problem: Both ssh -T github-personal and ssh -T github-work show the same username.

Solution: Ensure IdentitiesOnly yes is set in your SSH config. This prevents SSH from trying other keys in the agent first.

Permission denied errors

Problem: Getting "Permission denied (publickey)" errors.

Solutions:

  1. Verify the SSH key was added to the correct GitHub account
  2. Check that the key file path in SSH config is correct
  3. Ensure proper permissions: chmod 600 ~/.ssh/id_ed25519_github_*

Wrong Git identity in commits

Problem: Commits show wrong name/email.

Solution: Check your Git config and ensure includeIf is working:

git config --list --show-origin | grep user

URL rewriting not working

Problem: HTTPS URLs not converting to SSH.

Solution: Verify insteadOf rules in your Git config:

git config --get-regexp url

Risks & Mitigations

Common Pitfalls

  • Accidental cross-use: Committing to work repos with personal identity (or vice versa)
  • Key collisions: Misconfigured SSH hosts causing wrong key to be offered
  • Agent exposure: SSH agent forwarding exposing wrong key to remote hosts

Mitigations

  • Strict separation: Use clear hostnames (github-personal, github-work)
  • Per-directory configs: Use includeIf for automatic identity switching
  • Unambiguous naming: Name key files clearly to avoid confusion
  • Regular testing: Use the test matrix to verify correct behavior

Benefits of This Setup

Zero configuration per repository - works automatically
No password prompts for Git operations
Works with standard Git URLs - no special syntax to remember
Automatic identity switching based on working directory
Proper key isolation - each account uses its own SSH key
Portable configuration - works across different machines
Security best practices - proper permissions and key management
Developer-friendly - just use normal Git commands anywhere

File Structure

After setup, your configuration should look like:

~/.ssh/
├── id_ed25519_github_personal      # Personal private key
├── id_ed25519_github_personal.pub  # Personal public key
├── id_ed25519_github_work          # Work private key
├── id_ed25519_github_work.pub      # Work public key
└── config                          # SSH configuration

~/
├── .gitconfig                      # Global Git config
└── .gitconfig-work                 # Work-specific Git config

This setup provides a clean, secure, and developer-friendly way to manage multiple GitHub accounts on a single machine using Git's built-in features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment