On Demand ssh-add
For many years I have been bothered by the options for using the ssh-agent on Linux. I finally (hope) I've reached a reasonable solution for adding my keys to the ssh-agent.
As many *nix users know: SSH keys with passphrases are the way to go when
jumping from system to system. This is the case because on your main
computer there is a program running called
ssh-agent. When you first
boot your computer
ssh-agent knows nothing and doesn't do much.
The real magic happens when you tell
ssh-agent about your SSH keys. In
the past I've done this in one of two ways:
- Use the
ssh-addcommand to add a key to the agent.
- Have the desktop environment ask for your passphrase when it loads.
Since these have the same result of adding your passphrase to
it simply becomes a matter of user experience. Neither experience I really
In the first case, my use pattern was always:
$ ssh <hostname> Enter passphrase for key '<key>':
At which point I would curse, hit control-c, run
ssh-add, and try sshing
into the host. Not terrible, but not pleasant either.
The second option would pop up some graphical prompt asking for my passphrase when starting the desktop environment. This is also not a terrible experience, but it's a bit annoying when I'm just sitting down and don't want to type a long passphrase just to check my email. (I could close it, but then I'm back in the frustrating first case.)
What is a geek to do?
Honestly, the OS X way of doing this isn't too bad. If I haven't authenticated myself to the computer when I ssh the first time OS X recognizes that and prompts me for authentication. At this point I'm authenticated and any future SSH attempts will re-use that authentication. That is to say:
- OS X automatically adds the authentication to the ssh agent*
- I'm not bothered with authentication until I need it.
* This isn't quite how OS X actually does it, the passphrase is stored in a keychain. The keychain gets unlocked when I need it and serves the passphrase to the ssh command.
I want the same experience on Linux.
After searching for some tools to do it for me (and finding nothing), I
decide to take a stab at it. It turns out to be very easy. All I did was
add the following line to my
alias ssh="( ssh-add -l > /dev/null || ssh-add ) && ssh"
This just checks to see if any identities exist in the running ssh agent
ssh-add -l > /dev/null returns
1 if it is empty and
If there are identities, the
|| operation is short circuited and the ssh
command is run as normal. If the agent is empty, the
runs and asks for your passphrase as normal, adds it to the agent, (returns
0), and runs the ssh command as normal.
In both cases, any command line arguments are passed on to the final ssh command as
If you mistype your passphrase and
ssh-add gives up it returns
&& operation to short circuit and the normal ssh command is
not run and you can try again.
Of course, this makes a few assumptions:
- Either your agent is empty or it has all useful keys in it.
- You're going to
scpor use any other command.
In my case both assumptions a valid. I don't have any keys that
doesn't find automatically (even if I did, I would still want to manually
add them in them to the agent--in which case I am no worse off than
before). In the second case, I almost always ssh to a host before moving
files around or to, just so I can make sure I have the locations correct.
(Of course, as I submit this post
git asks for my passphrase because I
haven't authenticated yet. The quick answer is to alias all commands that
need ssh key authentication with the stuff before
&& and replace
with the desired command.)
This also shouldn't hurt security any more than another solution. At the end of the day, I'm disappointed that I didn't do this a long time ago.