Switch In Between Customers

Github and Gitlab setups with multiple accounts

Dirk Bolte
4 min readAug 16, 2020
Photo by Yancy Min on Unsplash

The challenge

More and more companies use cloud services from Github, Gitlab or Bitbucket. Now imagine you work for a company which requires you to work with an E-Mail address or account they manage. In parallel, you have another customer with the same requirement — or your private projects you work on with your private account. While you can easily login on the website, working with git on the command line or any IDE is a challenge: these services do not allow the same SSH key to be registered with two accounts. You will get an error doing so. You might face similar issues with GPG signing keys.

Error message when trying to re-use the same SSH key for a different user: The fingerprint has already been taken.
Error message when trying to re-use the same SSH key for a different user

Background

But why?

Git uses the SSH protocol for communication and the SSH key you specify. On the server side, the SSH server uses the public key for both identification and authentication purposes. It cannot differ in between users when two users have the same SSH key specified. Your SSH client on the other hand usually picks ~/.ssh/id_rsa as private key.

You can easily check how you are identified by Github (or Gitlab) by calling ssh -T git@github.com . You will see a message similar to this:

$ ssh -T git@github.comHi dirkbolte! You’ve successfully authenticated, but GitHub does not provide shell access.

This can be addressed on the server side or on the client side, but with the server not under our control, we have to find a way doing it on the client side.

Using two different SSH keys

Using OpenSSH, you can configure which SSH key to use in ~/.ssh/config . You can config various parameters e.g. on the level of a hostname. With still one hostname, you can still only use one key. But there’s another way.

SSH allows you to configure host names linking to other host names — and that’s what we’re about to do. Instead of using github.com , we will use customer1.github.com and point it to the original host. With that, we can also configure the ssh key that is used. ~/.ssh/config would get an entry like this (should work for both Linux and MacOS):

Host customer.github.com
Hostname github.com
UseKeychain yes
AddKeysToAgent yes
IdentityFile ~/.ssh/github-customer1
IdentitiesOnly yes

The corresponding SSH key you would generate with the following command line (-f parameter is the important one):

$  ssh-keygen -o -f ~/.ssh/github-customer1 -t rsa -b 4096 -C "My GitHub key for customer1"
Photo by Jen Theodore on Unsplash

Having this new SSH key, you log in with the credentials you have to use for your customer and upload the corresponding public key. You can verify this again using ssh -T git@customer1.github.com .

When now working with Github/Gitlab, you just have to ensure that you always use the correct hostname. So when cloning, you have to use customer1.github.com instead of github.com . Git now adds the corresponding host as remote. As Git would also use OpenSSH under the covers, OpenSSH’s config files and name resolution would be used, resulting it in using the correct SSH keys. It thereby also works with many IDEs.

In case you already have a repository, you can change the origin using the following command.

$ git remote set-url origin https://customer1.github.com/USERNAME/REPOSITORY.git

Git specifics

So now we use the right SSH key, but git itself has some parameters you might want to tailor, namingly, the email and GPG signing key. You can configure this per repository but it might be errorprone as you would have to redo this on every repo. Here you also have an alternative: .gitconfig .

A gitconfig has a [user] section, allowing to define the user name, email and GPG signing key. In order to use different configurations for this, we have to ensure different gitconfigs are applied. Bringing git to do so, we separate the repositories in different directories (which we should to anyhow 😃 ). So let’s create a ~/privatedev and a customer1dev directory. The corresponding directories are in these directories.

Now we create two additional gitconfig files: ~/.gitconfig.privatedev and ~/.gitconfig.customer1dev . Each of these config files can now contain a new [user] section like this:

[user]
name = <your name>
email = <email address for customer1>
signingkey = <The GPG signing key>

In your main config, you now configure to include a new config file when being in a specific directory using includeIf:

[user]
name = <default username>
email = <default email address>
signingkey = <default signing key>
[includeIf "gitdir:~/privatedev/*"]
path = ~/.gitconfig.privatedev
[includeIf "gitdir:~/customer1dev/*"]
path = ~/.gitconfig.customer1dev

So for every repository in the corresponding directory, the user configuration of the specific gitconfig is used.

Summary

Adjust SSH to define a new hostname for the user, making it use your new SSH key. Split repositories in different directories and create specific gitconfig files for them. Now you have a perfect separation in between user accounts for Github/Gitlab and between different customers. You can easily scale this to more customers or separations, whatever your needs are.

--

--