Note: Adding a few lines to the
.<name of shell>rc will not solve the problem here, since this particular ssh key has a password and that would not eliminate the need to keep typing it.
So I don't really understand how
ssh-agent works under the hood. I just use
ssh-add ~/.ssh/id_rsa every time I need to add a key to access some remote resource. One I've added the key once, I don't need to add it again for the same "shell session" ("shell session" is probably not the appropriate jargon).
Unfortunately, I'm creating new shell sessions all the time. I'm running zsh under tmux on OS X and have a ssh key creatively named
id_rsa. That ssh key has a password associated with it.
Every time I start a new shell I have to do the following
$ eval `ssh-agent` $ ssh-add ~/.ssh/id_rsa <type password>
which is really irritating.
I've noticed in the output of
ssh-agent that the
SSH_AGENT_PID environment variable is different every time. My hunch is that this environment variable and the
SSH_AUTH_SOCK are the reason that keys don't need to be re-added within a single shell session. When I call the
ssh program, it will use these environment variables to communicate with the
ssh-agent and authentication will succeed.
I'm wondering if there's a way of sharing
ssh-agents between sessions. Maybe the right approach is to add my SSH keys before starting
tmux and configure
tmux to preserve the
SSH_AGENT_PID environment variables. I'm really not sure. What's the standard way of solving this problem?
Here's a little snippet from my login scripts to handle what you want:
[ -f $SSHAF ] && . $SSHAF
# if ssh-agent not really running?
if [ -n "$SSH_AGENT_PID" ] && ! kill -0 $SSH_AGENT_PID >/dev/null
then ssh-agent >$SSHAF
ssh-add # add list of more keys here if needed
Explained: I'm saving the environment setting variables from ssh-agent in a dotfile in $HOME (.ssh_agent_env) I source that file if it exists (line 2) to get the process id of the (possibly) running ssh-agent. (SSH_AGENT_PID variable) If that SSH_AGENT_PID variable is set, I check to see if the agent is running with a kill -0 on it's PID (kill -0 sets return code to 0 (true) if the process is running, 1 (false) otherwise. If the agent isn't running I start it and save the output in the .ssh_agent_env file, source that file to add the values to my shell session, and run ssh-add to cache my keys.
The first time on the system, no file exists so the agent is started. Any time after that the file exists, we verify if the agent is running. If not we do a startup.
Note: this is my running implementation of the solution 2 of the first answer above.
The primary variable is the
SSH_AUTH_SOCK variable; the
SSH_AGENT_PID is only used with
ssh-agent -k to kill the running agent.
So the standard approach is to run
ssh-add your keys, then run
Now the fun part of this is that you can reconnect to the
tmux daemon and your ssh agent session will still be there and running. So you can do things like disconnect, logout, login again, reconnect to running tmux and not need to re-enter your key password.
(This is good on a single-user machine; not so good on a shared machine 'cos the
root user could abuse your keys!)
ssh-agent does, is that it starts itself in the background, and prints a bunch of environment variables that the
ssh client utility uses to know how to reach the agent (mostly the path of the socket in
SSH_AUTH_SOCK). If you start the agent again, you get multiple copies running, but you can usually reach only one from a single shell... (check with something like
ps uax | grep agent to see how many you are running.) When
ssh-add is run, it contacts the agent, and asks it to read a key to memory. After that any
ssh clients that connect to the same
ssh-agent instance can take advantage of the saved key.
Couple of choices to run only one
ssh-agent before you start your
tmux session (or
screen for that matter). The environment variables set at that point should be inherited to all shells you run under
screen. (I don't know if
tmux needs special configuration to not clean environment variables.)
I've been (the wrong type of) lazy, so I've just done that manually each time before starting my
screen session, but it would be easy to create a script to both start the agent and then the
If you consider something like a graphical desktop environment, you should start the agent when the DE starts, if possible, so that the environment variables will be available to any terminals you start.
2) Create a script that checks if an
ssh-agent is running, and if not, starts it, saving the environment variables to a file. If it is running, the script can then read the same variables from the file. Source the script from the shell's
.bashrc) or equivalent. (Source, as in with. myagentscript.sh`)
In either case, the issue is with pointing the environment variables to the same
ssh-agent. Any keys you add to one instance of the agent should be visible to all users of the same agent, regardless of if what shell you
ssh-add them from.
As an aside,
can take an argument to define how long the keys shall be saved: running
ssh-add -t 3600 my-key-file
will tell the agent to forget about the key after an hour. This may be useful to reduce the time during which the keys are unencrypted in memory.
Ideally, you'd start
ssh-agent only once, and run
ssh-add only once, and the subsequent shells will inherit the agent.
If you're logging in through a GUI and your window manager uses
.xinitrc, you may add the following to that file:
if [ -z "$SSH_AUTH_SOCK" ]; then
This means that the agent will be inherited for any process (
xterm or other terminal emulator) that the window manager spawns.
If you work without X11, then feel happy for a bit because you're awesome, and then add those lines to your
.profile shell initialization script.
eval will take the output from
ssh-agent and evaluate it in the current shell, setting
SSH_AGENT_PID to whatever the values are. Then
ssh-add will be run, pretty much as you're doing manually. The agent will then be inherited by the
tmux session you're likely to start soon after logging in (unless you've set
tmux to be your actual login shell, which is possible).
In a perfect world, you then only have one running SSH agent and won't have to give any passwords ever again... until you log out and in again, or log in on another console.