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
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 casegithub-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
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
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)
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
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
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"
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.
Top comments (0)