DEV Community

TheArktect
TheArktect

Posted on

Using multiple SSH keys on multiple Git repositories

If you have multiple Git repositories, and use different Git hosting services, like GitHub, GitLab, Azure... while using SSH as the authentication means to interact with your code on these repositories, you probably have (or should have) multiple SSH keys.

Contrary to what some would assume, Git doesn't manage the SSH keys on the system, it uses the SSH daemon available in your system, which most probably will be OpenSSH, to establish encrypted and secure connections through the network.

Here we'll discuss how you can configure OpenSSH with Git, so that we can use multiple SSH keys for multiple Git hosting services, or even, multiple repositories within the same service.

About OpenSSH

OpenSSH is developed by the OpenBSD team. OpenBSD is a Unix-like operating system regarded for it’s security and robustness, and the same goes for their projects, like OpenSSH. OpenBSD has great manual pages, and I highly recommend to read them if you want to do a deep dive on how OpenSSH works.

Generating keys

You may already have your SSH keys created, but if you need enlightenment or guidance on how to create SSH keys, you can access this Github article about generating a new SSH key.

One point that is important to notice, is to know what type algorithm we are using to create an SSH key. The GitHub article talks about two algorithms we can use: ed25519 (the preferred one) and RSA (which is already legacy).

If you have old RSA SSH keys, I highly recommend you to re-create them with the newer ed25519 algorithm, but if you prefer to use the older RSA keys, you'll need to make some tweaks in our configurations depending on your operating system (more on that later).

Creating the config file

By default OpenSSH will use the ~/.ssh folder to store is config file and your SSH keys. Seach for ~/.ssh and make sure that the file named config exists, if not, just make sure the create both the folder and config file.

Now you can start editing the config, the syntax is pretty straightforward, here is an example:

Host github.com
        HostName github.com
        IdentityFile ~/.ssh/github-key
        IdentitiesOnly yes
Enter fullscreen mode Exit fullscreen mode

In this file we are basically determining that:

  • Host is your alias for the website (more on that later).
  • HostName is the real website name you’ll be interacting with.
  • IdentityFile points to the private SSH key.
  • IdentitiesOnly tells OpenSSH to only look to the identity files given in the specific config in this case github-key

With that entry done, once you have a repository that points to github.com, OpenSSH will try to establish the communication with GitHub's servers using the appropriate SSH key. In this case, we are assuming you want to use the same SSH key to all your repositories inside the same Git hosting website.

You can also have multiple different services too:

Host github.com
        HostName github.com
        IdentitiesOnly yes
        IdentityFile ~/.ssh/github

Host gitlab.com
        HostName gitlab.com
        IdentitiesOnly yes
        IndeitityFile ~/.ssh/gitlab
Enter fullscreen mode Exit fullscreen mode

That’s good, we’ll now be able to have one SSH key for GitHub and one for GitLab. You can create as many hosts like these for different Git hosting services, and we'll always use the same keys for all repositories under each Git hosting services, but what if you have to use 2 or more SSH keys for different projects just inside GitHub? This is where aliases come in.

Host aliases

You can define your own aliases on Host names so you can have multiple SSH keys that point to only one service. Imagine that you have 2 repositories that use different SSH keys on GitHub:

Host project1.github.com
        HostName github.com
        IdentitiesOnly yes
        IdentityFile ~/.ssh/github-project1

Host project2.github.com
        HostName github.com
        IdentitiesOnly yes
        IdentityFile ~/.ssh/github-project2
Enter fullscreen mode Exit fullscreen mode

As you can see we have pre-pended the Host with the project name, this will give us a custom URL, or alias, to use inside our git repositories.

These aliases will help OpenSSH to identify what SSH key it needs to use, while making sure to connect to the right service, which we provided on HostName. Notice that both Host entries here, point to the same HostName (the same Git hosting service).

Now inside your already cloned Git repository, you can change the remote URL to match the Host alias. By default your "project1" folder will point to the default GitHub URL:

git remote -v # List the remote repositories
origin  git@github.com:your_user_name/project1.git (fetch)
origin  git@github.com:your_user_name/project1.git (push)
Enter fullscreen mode Exit fullscreen mode

Now we need to change it so it matches our alias project1.github.com:

git remote set-url origin git@project1.github.com:your_user_name/project1.git
Enter fullscreen mode Exit fullscreen mode

See how we only changed the portion after the @ and before the : symbol? The rest is the same, your username and project name. We are effectively just changing the URL we are pointing to.

Now every time we fetch, push, pull... inside this repository, Git will forward the whole string git@project1.github.com:your_user_name/project1.git to OpenSSH, which will in turn search only for the URL: project1.github.com, and match it against its config file. If it does find the URL in one of the Host entries, it'll select the correct SSH key to communicate with the website. That's where HostName comes in, when OpenSSH establishes the real connection, it will changes our custom URL for what we provided in HostName.

You can then, go to your second project and repeat the same process, just making sure to name the remote repository like the alias you intend it to use.

Dealing with RSA keys

Remember that the type of key you choose is important? Most websites these days use ed25519, which is default, but some services may still use RSA, in this case, many Linux systems (like Fedora) and Git on Windows (Git Bash) won’t want to use these keys by default.

To use an RSA key we need to specify some parameters inside the Host config. By the time of the original writing (2021), Microsoft Azure only works with RSA keys, this is from my personal config:

Host ssh.dev.azure.com
        HostName ssh.dev.azure.com
        IdentitiesOnly yes
        PubkeyAcceptedAlgorithms +ssh-rsa
        HostkeyAlgorithms +ssh-rsa
        User git
        IdentityFile ~/.ssh/azure
Enter fullscreen mode Exit fullscreen mode

We need to pass PubkeyAcceptedAlgorithms and HostkeyAlgorithms the parameter +ssh-rsa so that OpenSSH accepts to communicate through RSA keys.

Warning, depending on your version of OpenSSH and other system configurations, passing this 2 parameters inside your SSH config file will give you an error, this means that OpenSSH is old enough and doesn't have these options. You can then simply remove these lines.

Git Config

After version 2.10, Git now has a native method of choosing SSH keys, even though it’s not as flexible like using OpenSSH native config file, it’s still an option.

Inside a Git repository we can use the command bellow to tell Git to invoke the ssh command with some default parameters:

git config core.sshCommand "ssh -i ~/.ssh/your-private-key"
Enter fullscreen mode Exit fullscreen mode

This will change the local repository config, found under .git/config. Even though it can help you achieve what you want, it needs to be configured for every repository regardless if you are using only one SSH key for all repositories inside a Git hosting service.

You could also update the global Git config file, but that would be used on all repositories. A solution that is far from ideal.

Hot sauce if you're wrong - web dev trivia for staff engineers

Hot sauce if you're wrong · web dev trivia for staff engineers (Chris vs Jeremy, Leet Heat S1.E4)

  • Shipping Fast: Test your knowledge of deployment strategies and techniques
  • Authentication: Prove you know your OAuth from your JWT
  • CSS: Demonstrate your styling expertise under pressure
  • Acronyms: Decode the alphabet soup of web development
  • Accessibility: Show your commitment to building for everyone

Contestants must answer rapid-fire questions across the full stack of modern web development. Get it right, earn points. Get it wrong? The spice level goes up!

Watch Video 🌶️🔥

Top comments (0)

👋 Kindness is contagious

Please show some love ❤️ or share a kind word in the comments if you found this useful!

Got it!