Managing SSH keys using keychain
As a developer you probably work on projects that live on GitHub or some other repository. If you are anything like me you have several accounts and each requires its own SSH identity. Or maybe you’ve just noticed that each time you login you have to:
- Start a new ssh-agent process
- Add SSH identities to the agent
- Enter you passphrase
Naturally doing this every time you start a new session is tiresome and lame. In this post I demonstrate how to use keychain to automate this at login. I’ll also share how to configure SSH in such a way that the correct SSH identity is used when dealing with multiple accounts.
We’ll be using the OpenSSH package which contains utilities to facilitate ssh communication as well as generate ssh keys. We are going to delegate management of these ssh keys (identities) to the Keychain. Keychain has the added benefit of allowing one long-running ssh-agent process per system, rather than per login. No more starting the ssh-agent everytime we login. Yay!
First things first, make sure you have OpenSSH installed on your system. You may already have this installed by default depending on what system you are running. There are a variety of ways to check this. I suggest using your system’s native package manager (pacman, dpkg, etc) to query for its existence. Alternatively, look for a running ssh daemon (ssh or sshd) or service (systemctl).
$ pacman -Qi openssh
$ dpkg -l | grep openssh-server
$ systemctl status ssh
$ ssh -V
Install the OpenSSH package:
$ sudo pacman -S openssh
$ sudo apt-get install openssh-server
$ sudo systemctl enable ssh $ sudo systemctl start ssh
Generate new SSH key
If you are starting from a fresh SSH installation you won’t have any ssh keys at this point. So let’s create one. Make sure to substitute [firstname.lastname@example.org] with your email address.
$ cd ~/.ssh $ ssh-keygen -t ed25519 -C "[email@example.com]" Generating public/private rsa key pair.
$ sudo pacman -S keychain
$ sudo apt-get install keychain
Keychain drives both
ssh-add so we don’t have to. The best part is Keychain also maintains a single
ssh-agent process for us.
That’s a very good thing because if you created your ssh key using a passphrase you’ll only need to provide it once across multiple login sessions.
When a new shell session is created (aka we log in) we want the keychain to provide the necessary environment variables for an SSH client to be able to find our agent. We let it do the work of:
- Adding the keys to the agent
- Managing the agent between sessions.
Add the following to
eval $(keychain --eval --quiet id_ed25519 id_rsa)
In the above example we are using some bash to:
- Execute the output of our keychain command.
- Use the
--evalswitch which causes the keychain to output the lines needed to set the above mentioned environment variables.
- Use the
--quietswitch so keychain will only display warnings and errors when this file is sourced.
- Lastly, we provide the keychain with a space delimited list of keys we want added to the ssh agent.
If you use a single ssh key that you are managing, with GitHub for example, then you are done. If you have two accounts with a single host or multiple hosts, we are almost done.
Configure SSH for multiple hosts or accounts
We have added our SSH keys to the keychain. All that is left to do is tell the SSH agent which key to use for a given host (GitHub, Google, AWS, whatever). We do that using a configuration file stored in the same location as our keys.
~/.ssh/configif one does not exist.
Hostentry for each host and/or each account.
# work account Host github.com-work HostName github.com User git IdentityFile ~/.ssh/id_rsa_work # Personal account Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa # GCP account Host google.com HostName source.developers.google.com User git IdentityFile ~/.ssh/id_ed25519_google
- Host - This is just a label or alias.
- HostName - The real host name that you will log in to (e.g. Github.com).
- User - The username to use to log in (e.g. “git”, “tsmith”, etc).
- IdentityFile - The ssh private key to use.
In this example, my first entry has a Host entry called, “github.com-work”. That’s not a real host URI (not that I know of anyway). This is just a label or alias. The SSH agent will substitute this value with the value of HostName. This allows me to use 2 different ssh keys with a single host. This allows me to have multiple ssh keys associated with a single host.
# ssh will use ssh key '~/.ssh/id_rsa_work' $ ssh github.com-work # ssh will use ssh key '~/.ssh/id_rsa' $ ssh github.com
Using the same example configuration, lets say my work repository lives here:
I can clone this repository using the Host value associated with my work ssh key (IdentityFile):
# notice the use of github.com-work rather than github.com $ git clone firstname.lastname@example.org:SuperRocketCo/ignition-module.git ... $ git remote -v origin email@example.com:SuperRocketCo/ignition-module.git (fetch) origin firstname.lastname@example.org:SuperRocketCo/ignition-module.git (push)