Skip to main content

posts

Configure SSH Cleanly for Multiple GitHub Accounts

A clean SSH configuration pattern for using multiple GitHub or Bitbucket accounts from one machine.

SSH key authentication is simple when there is only one account.

Create a key pair. Add the public key to GitHub or Bitbucket. Clone the repository. Done.

The problem starts when one machine needs access to more than one account on the same service.

For example:

  • a private GitHub account
  • a company GitHub account
  • a customer GitHub organization
  • one or more Bitbucket workspaces

All GitHub repositories still use the same real host:

github.com

If all keys are thrown into ~/.ssh, SSH may try the wrong key first. Authentication then depends on key order, agent state, and other details that are easy to forget. Very modern: security by drawer full of mystery files.

A cleaner solution is to use SSH host aliases and one small config file per account.

The Basic Idea

SSH does not have to connect directly to the host name written in the Git URL. The Host entry in ~/.ssh/config can define an alias.

This means github.com-private can point to the real host github.com, but use a specific private key.

The Git remote then uses the alias:

git@github.com-private:ralph/project.git

instead of:

git@github.com:ralph/project.git

The alias selects the account-specific SSH key.

Directory Layout

Keep each account in its own directory.

Example:

~/.ssh/
├── config
├── github-private/
│   ├── config
│   ├── key
│   ├── key.pub
│   └── readme.md
└── github-company/
    ├── config
    ├── key
    ├── key.pub
    └── readme.md

The top-level config file only includes the account-specific config files.

Include ~/.ssh/github-private/config
Include ~/.ssh/github-company/config

This keeps the main file short. It also makes it obvious which key belongs to which account.

The readme.md file is optional, but useful. Write down what the key is for:

GitHub private account for Ralph.
Public key added to https://github.com/settings/keys.
Created: 2026-06-05.

Future you will appreciate this. Future you is usually the person asking why a random file called id_rsa_old2_final exists.

Create the Keys

Create one key pair per account.

For a private GitHub account:

ssh-keygen -t ed25519 -f ~/.ssh/github-private/key -C "github-private"

For a company GitHub account:

ssh-keygen -t ed25519 -f ~/.ssh/github-company/key -C "github-company"

Add each .pub file to the matching account in GitHub or Bitbucket.

For GitHub, this is usually:

Settings → SSH and GPG keys → New SSH key

Do not add the same key to multiple personal accounts. Use separate keys. It makes access control and cleanup much easier.

Configure the Private Account

Create this file:

~/.ssh/github-private/config

Content:

Host github.com-private
    HostName github.com
    User git
    IdentityFile ~/.ssh/github-private/key
    IdentitiesOnly yes

The important parts are:

  • Host github.com-private defines the alias.
  • HostName github.com defines the real server.
  • User git is the SSH user used by GitHub.
  • IdentityFile selects the private key.
  • IdentitiesOnly yes prevents SSH from trying every key in the agent.

Configure the Company Account

Create this file:

~/.ssh/github-company/config

Content:

Host github.com-company
    HostName github.com
    User git
    IdentityFile ~/.ssh/github-company/key
    IdentitiesOnly yes

The two configs point to the same real server, but they use different aliases and different keys.

File Permissions on Linux and macOS

OpenSSH is strict about private key permissions.

Use:

chmod 700 ~/.ssh
chmod 700 ~/.ssh/github-private ~/.ssh/github-company
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/github-private/config ~/.ssh/github-company/config
chmod 600 ~/.ssh/github-private/key ~/.ssh/github-company/key
chmod 644 ~/.ssh/github-private/key.pub ~/.ssh/github-company/key.pub

The private key must not be readable by other users.

On Windows, the same layout works with the built-in OpenSSH client and PowerShell. The home directory is available as ~, for example:

cd ~

The SSH directory is normally:

C:\Users\<user>\.ssh

Windows file permissions are different, so chmod is only relevant when using a Unix-like environment such as WSL or Git Bash.

Test the Configuration

Test the private account:

ssh -T git@github.com-private

Or, because User git is already configured:

ssh -T github.com-private

For GitHub, a successful login looks like this:

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

For detailed debugging, use:

ssh -Tv github.com-private

Look for lines showing which config file and identity file are used.

Then test the company account:

ssh -T github.com-company

If the wrong account responds, check these items first:

  • Is the correct public key added to the correct GitHub account?
  • Does the alias in the Git remote match the Host entry?
  • Is IdentitiesOnly yes set?
  • Is the private key path correct?
  • Are the file permissions acceptable to OpenSSH?

Use the Alias in Git Remotes

When cloning, replace the real host name with the alias.

Private account:

git clone git@github.com-private:ralph/project.git

Company account:

git clone git@github.com-company:company/important-project.git

For an existing repository, update the remote URL.

Check the current URL:

git remote -v

Set the new URL:

git remote set-url origin git@github.com-company:company/important-project.git

After that, normal Git commands use the configured key:

git fetch
git pull
git push

Bitbucket Works the Same Way

The same pattern works for Bitbucket.

Example:

Host bitbucket.org-company
    HostName bitbucket.org
    User git
    IdentityFile ~/.ssh/bitbucket-company/key
    IdentitiesOnly yes

Clone with:

git clone git@bitbucket.org-company:company/project.git

The exact repository path depends on the service and workspace, but the SSH principle is the same.

Why This Is Cleaner

This pattern has several advantages:

  • each account has one dedicated directory
  • each account has one dedicated key pair
  • the main SSH config stays small
  • Git remotes explicitly show which account is used
  • old keys can be removed without guessing their purpose
  • more accounts can be added without turning ~/.ssh into a junk drawer

It also avoids relying on SSH agent key order. That matters when a developer has many keys loaded, which is common on machines used for private work, company work, and customer projects.

Limitations

This does not replace proper access management.

Remove unused keys from GitHub or Bitbucket. Rotate keys when a machine is lost. Do not share private keys between users. Do not copy one private key across many machines unless there is a deliberate reason.

For company environments, follow the organization policy. Some teams prefer managed developer devices, SSO, short-lived credentials, or hardware-backed keys. SSH config aliases do not replace those controls.

Conclusion

Multiple GitHub or Bitbucket accounts are easier to manage when each account has its own SSH key and its own config file.

The useful trick is the Host alias:

Host github.com-company
    HostName github.com
    User git
    IdentityFile ~/.ssh/github-company/key
    IdentitiesOnly yes

Then use the alias in the Git remote:

git@github.com-company:company/project.git

This keeps authentication explicit. It also makes the setup easier to understand months later, when nobody remembers which key was created for which account. Which, obviously, would never happen to us.