Juggling SSH keys when using multiple GitHub accounts

As part of my consulting work at Human Made I contribute code to a number of different client GitHub organizations. A recent client project introduced a security requirement that all project contributors must use a GitHub account dedicated to that organization alone, precluding the use of our standard GitHub accounts. Creating a new GitHub account is straightforward, but as GitHub accounts cannot share SSH keys we ran into trouble when we needed to regularly switch between our primary account when interacting with internal Human Made administrative repositories and the new SSH key used for the client project.

A quick web search turned up this ssh config-based approach for specifying per-repository SSH keys. Unfortunately we encountered the same issue noted in the comments on that gist, where a change was needed within the .git/config file before the correct key would be used. This doesn’t work in our case because it requires too much manual intervention when working with a large number of repositories. Fortunately, with assistance from our client’s team we were able to come up with an alternative workaround; it’s slightly awkward, but functional!

Assuming that all of our development for this client project will occur within ~/client/, and that our new private key is located at ~/.ssh/id_rsa_client, this bash script will check whether we’re within the client directory tree and contextually set an environment variable instructing Git to use the new private key:

#!/bin/bash

# When running `git`, if we are within the client
# project directory, set Git to use a specific SSH
# private key; otherwise, act as normal.
if [[ $PWD == $HOME/client* ]];
then
  GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_client" /usr/bin/git $@
else
  /usr/bin/git $@
fi

The conditional [[ $PWD == $HOME/client* ]] uses simple substring matching to validate whether our current working directory ($PWD) begins with our client directory $HOME/client (or ~/client). If so, set the environment variable and pass all received arguments to git, otherwise use Git as normal.

Name this file git, make it executable, put it somewhere in your PATH, and we’re back in business.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.