Understanding ssh-agent and ssh-add
You may have come across the following message when doing some operation that uses your private key, such as working with git or ssh:
Enter passphrase for key '/home/user/.ssh/id_rsa':
So you go ahead an enter your password, allowing the key to be used. This is fine, at least for the first time. You definitely want a passphrase on your keys, so that there's some level of security against someone hijacking your computer, but you don't want the inconvenience of having to type your passphrase every damn time you use your key.
ssh-agent and ssh-add
You can fix this problem with a combination of
ssh-add. The agent should be running in the background, which allows us to use
ssh-add to permanently authorise the use of our keys for the agent's session.
For too long I didn't understand the basic operation of these commands, so I took a shotgun approach to managing my key authorisation (mainly lifted from various blog posts, which were few and far between). For a long time, I lived with this code in my shell's configuration file without understanding what it was doing:
eval $(ssh-agent) > /dev/null
This created a new agent every time I started a new shell (i.e. a new terminal tab, or a new window in tmux). If I had 10 windows open, which isn't unusual, I would have 10 ssh-agents running. On top of this, I would have to run
ssh-add in every shell to allow the use of my keys, or suffer the repeated requests for my key's passphrase.
This was clearly the wrong way of doing things, and I couldn't find a single post that seemed to recognise my problem, let alone offer a sensible solution. So I took a step back and started looking at how the agent worked.
A closer look at ssh-agent
ssh-agent in your terminal starts a daemon process and outputs a few lines of shell script:
$ ssh-agent SSH_AUTH_SOCK=/tmp/ssh-MUyniqn10506/agent.10506; export SSH_AUTH_SOCK; SSH_AGENT_PID=10507; export SSH_AGENT_PID; echo Agent pid 10507;
We can check that the agent is running:
$ ps x | grep ssh-agent 10507 ? Ss 0:00 ssh-agent
If we take a closer look at the shell script that the command spat out, we can see that it's setting some environment variables. Specifically, it's setting
$SSH_AGENT_PID is set to the PID of the agent daemon, which we confirmed by checking the process table. This is used by
ssh-agent -k, which kills the agent whose PID is set in that environment variable. It's not essential for
$SSH_AUTH_SOCK contains the path of the unix file socket that the agent uses for communication with other processes. This is essential for
ssh-add. If you try to run
ssh-add without this environment variable set, or with an incorrect one, you will get the following error:
Could not open a connection to your authentication agent.
I don't fully understand the design decision behind
ssh-agent, which prints fairly essential information out as executable code, and doesn't update the current shell with the required environment variables; that just seems a bit bizarre to me. But it is what it is, and the bottom line is that we need to keep track of our agent's file socket to be able to be able to remember the passphrases for our keys across multiple shell sessions.
Starting the ssh-agent and updating the current shell
Very simply, instead of running
ssh-agent and having to copy and execute the output to your current shell, you can just evaluate the output:
$ eval $(ssh-agent) > /dev/null
The output redirect just gets rid of the printed "Agent pid blah blah".
We can then run
ssh-add, which unlocks our key permanently (or start the agent with the
-t switch to specify a lifetime), allowing us to have blissful, uninterrupted private-key-based activity; truly the stuff of dreams.
Using the same agent across multiple shell sessions
It would be a pain to have to manually set the
$SSH_AUTH_SOCK environment variable in every new shell session. As first-world developer problems go, this ranks quite highly. Fortunately, a delightful chap named Wayne Walker has written a small bash script to locate compatible ssh-agent processes and update the environment accordingly - you can find it on github here.
Download it somewhere accessible (e.g.
~/.ssh-find-agent) and add the following to your shell's configuration file (e.g.
source ~/.ssh-find-agent/ssh-find-agent.bash set_ssh_agent_socket
Each new shell session will look for an existing ssh-agent session and update the
$SSH_AUTH_SOCK environment variable. If you have run
ssh-add previously then you won't need to reauthorise your keys.
Nice one Wayne!