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.
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
.
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 = "";
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=
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
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