Skip to content

Instantly share code, notes, and snippets.

@madidier
Created December 22, 2023 22:52
Show Gist options
  • Save madidier/a9190a58fa43b905b5070b6382e1fa2c to your computer and use it in GitHub Desktop.
Save madidier/a9190a58fa43b905b5070b6382e1fa2c to your computer and use it in GitHub Desktop.
Alternative SSH key switching approach to switch accounts on GitHub

Background

My need was to be able to easily switch the SSH key used to authenticate to GitHub because I have a work account and a personnal account. I know of this method, but it would be very unpractical on my codebases.

The reason is that I use Nix flakes both on personnal and on professional projects - and those flakes tend to reference other, private flakes. Flakes have lockfiles that pinpoint dependecies via their git+ssh: urls, and the aforementioned method would require messing with these URLs. In other words, I need git+ssh://git@github.com/org/repo to stay as it is and not become something like git+ssh://git@github.com-work/org/repo so that my Nix flakes and other dependency-pinning tools can work with private repos.

I did some reading on man ssh_config and came up with an enhanced method that fixes it for me. I'm providing the code I inserted in my Home Manager config along with instructions on how to achieve this if you are not using Home Manager.

The SSH keys

My keys use ed25519 signatures, my personnal key is located at the default ~/.ssh/id_ed25519 path and alternatives are suffixed as in ~/.ssh/id_ed25519_acme. You may use any type of key and naming scheme, just adapt the instuctions below.

To generate the alternate key, I ran ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_acme.

Home Manager Setup (skip if you don't use HM)

Just add this somewhere in your Home Manager config:

programs.ssh.enable = true;
programs.ssh.matchBlocks."github.com".identityFile = "~/.ssh/id_ed25519\${CURRENT_GITHUB_KEY_SUFFIX}";
# Set an empty default value; ssh will error out if the environment variable does not exist:
home.sessionVariables.CURRENT_GITHUB_KEY_SUFFIX = "";

Classic approach (skip if you use HM)

Add the following to your ~/.ssh/config:

Host github.com
  IdentityFile ~/.ssh/id_ed25519${CURRENT_GITHUB_KEY_SUFFIX}

And to set the default SSH key, add this to your .bashrc or whichever location you prefer to set session environment variables:

# Set an empty default value; ssh will error out if the environment variable does not exist:
export CURRENT_GITHUB_KEY_SUFFIX=

Simple usage

Now, you will be able to switch SSH keys via an environment variable. You can do so manually, i.e. in bash:

# To switch keys for the remainder of the current session:
CURRENT_GITHUB_KEY_SUFFIX=_acme
# To override the ssh key just once:
CURRENT_GITHUB_KEY_SUFFIX=_acme git clone git@github.com/acme/project

Direnv usage

Our projects also use direnv, so I set up direnv to automatically switch keys for me.

First, the project needs to be set up so that it will load your private .env.local file if you have one:

# To be included in .envrc:
dotenv_if_exists .env.local

The .env.local file should be ignored:

echo .env.local >> .gitignore

And finally, set up your local variable:

echo CURRENT_GITHUB_KEY_SUFFIX=_acme >> .env.local
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment