Avoid separately adding ssh keys (with password) to shell sessions

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-agent and 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_AUTH_SOCK and 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
     . $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-agent, then ssh-add your keys, then run tmux.

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!)

Basically, what 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:

1) Start 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 tmux or 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 screen/tmux session.

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 .profile (or .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, ssh-add 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 .xsession or .xinitrc, you may add the following to that file:

if [ -z "$SSH_AUTH_SOCK" ]; then
  eval $(ssh-agent)

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 .bash_profile or .profile shell initialization script.

The eval will take the output from ssh-agent and evaluate it in the current shell, setting SSH_AUTH_SOCK and 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.

Category: tmux Time: 2016-07-29 Views: 1
Tags: ssh agent tmux

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development


Front-end development


development tools

Open Platform

Javascript development

.NET development

cloud computing


Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.115 (s). 12 q(s)