71

I'm trying to have the following commands be auto-executed when I login to my server via ssh:

ssh-agent /bin/bash
ssh-add ~/.ssh/id_rsa

My ssh key has a passphrase and I'm fine with entering it once per login.

I tried putting this in my .bashrc file, however I believe that ssh-agent starts a new bash session. When I try to login after having this in my .bashrc, it gets stuck, and I have to type 'exit' to then see the 'enter passphrace to unlock key' prompt

Any other suggestions?

Server is running Ubuntu LTS

6 Answers6

82

You can try adding this:

eval $(ssh-agent -s)
ssh-add ~/.ssh/id_rsa

This way the ssh-agent does not start a new shell, it just launches itself in the background and spits out the shell commands to set the appropriate environment variables.

As said in the comment, maybe you do not want to run the agent at all on the remote host, but rather on the box you are working from, and use

ssh -A remote-host

to forward the services of your local ssh agent to the remote-host.

For security reasons you should only use agent forwarding with hosts run by trustworthy people, but it is better than running a complete agent remotely any time.

Matt
  • 322
  • 2
  • 3
  • 12
Tobi Oetiker
  • 1,892
  • When I replace ssh-agent /bin/bash with ssh-agent -s, and then I try to do git pull, I'm still asked for the passphrase of the private key to unlock it. That's not really what I want, I want to only have to enter the passphrase on doing ssh-add, and not have to repeat it each time I run any git commands. Any ideas? – Click Upvote Mar 03 '15 at 08:34
  • and running the agent locally and using ssh -A is not an option for you? The problem is, that you can not 'restart' the ssh-agent on every connection. Every time you start it, it knows 'nothing' and when you ssh-add the key you will have to decrypt it ... – Tobi Oetiker Mar 03 '15 at 11:09
  • for your .ssh/config file: Host remote-host ControlMaster auto ControlPath ~/.ssh/master-%l-%r@%h:%p ControlPersist 2h – Tobi Oetiker Mar 03 '15 at 11:10
  • Running ssh -A works fine. The problem is, I'd just like to have a bash script which runs ssh-agent and ssh-add , rather than have to run those separately each time. I'm fine with running this script manually and then doing ssh -A. The problem is, running ssh-agent from a bash script doesn't work. And if I do ssh-agent -S, then doing git pull still asks for the pass phrase. – Click Upvote Mar 03 '15 at 22:18
  • I think the problem is this: "it just launches itself in the background and spits out the shell commands to set the appropriate environment variables." I assume that after running ssh-agent -S I'd need to set those env. variables before git pull will work. Can that be done automatically from a bash script? That way I just have to run ssh.sh and enter my passphrase, and from there everything works on auto pilot. – Click Upvote Mar 03 '15 at 22:20
  • if the ssh-agent is running and the environment variable are set, then the keys will be added to is automatically after first use ...I guess I am not quite sure what your use case is ... it would help if you edited your question with the commands you expect to be able to run. Also note that running a bash script and executing .bashrc are two different things. If you set a variable in a bash script it can never affect the calling process. Environment variable changes will not work backwards. You may want to setup an alias for such a purpose. – Tobi Oetiker Mar 04 '15 at 05:08
  • The environment variables are not set.. I'm wondering if there's a way to set them automatically when ssh-agent -S is run? – Click Upvote Mar 04 '15 at 07:17
  • I'd like to ideally run one single command, either an alias or a bash script, which in turn starts ssh-agent and calls ssh-add . And then I enter my passphrase once and no longer have to enter it again. – Click Upvote Mar 04 '15 at 07:18
  • could it be that you work on host a, login to host b, start the agent, run your git command, log out of b, and then login to b again ? in that case your agent connection will get lost every time ... unless you run your agent on host a and use ssh -A to log into b. – Tobi Oetiker Mar 04 '15 at 09:01
  • Connecting is not even an issue. This is limited to my own machine now. I'm just looking for a simple way to have ssh-agent and ssh-add be executed via a bash script or such on my own machine. Is that possible? – Click Upvote Mar 04 '15 at 22:35
  • note that the environment variables only get inherited by the children of your process ... so in a desktop environment, ssh-agent normally gets launched in the startup phase and is the 'parent' of most of the processes and they thus inherit its environment variables ... your distribution should actually take care of this. – Tobi Oetiker Mar 05 '15 at 16:22
  • On my local machine, I open shell, run ssh-agent -S. It outputs the variables. And then I run ssh-add ~/.ssh/id_rsa. It says key was added. Then in the same session I run git pull which works if I run ssh-agent /bin/bash, however it asks me for the pass phrase to unlock it. So ssh-agent -S is not working. – Click Upvote Mar 05 '15 at 21:22
  • you have to run \ssh-agent -s`` note the backticks!! – Tobi Oetiker Mar 11 '15 at 07:42
  • bash: SSH_AUTH_SOCK=/tmp/ssh-AmnQ6sdALZOT/agent.3986;: No such file or directory – Click Upvote Mar 12 '15 at 00:09
  • 1
    oops just realised in bash you need an extra eval in front of the ssh-agent call .. updated my answer above – Tobi Oetiker Mar 12 '15 at 23:15
  • I've made a bash script which contains the eval ssh-agent -s and ssh-add lines as you gave (with backticks). When I run this, I get the output: Agent pid 3328 Enter passphrase for /home/xx/.ssh/id_rsa: Identity added: /home/xx/.ssh/id_rsa (/home/xx/.ssh/id_rsa). However, after this if I try git pull, I'm still prompted to enter keyphrase to unlock the key, which sucks. If I run ps -aux | grep ssh I can see that the agent is running. If I subsitute ssh-agent /bin/bash for eval ssh-agent -s, then git pull works. But that can't be put in a bash script. Any ideas? – Click Upvote Mar 15 '15 at 09:17
  • yes, because the bash script will run in a separate process, it can not influence the environment of the calling process .. – Tobi Oetiker Mar 15 '15 at 13:33
  • so there's no way to do what i want? – Click Upvote Mar 16 '15 at 07:47
  • 1
    you could create an alias – Tobi Oetiker Mar 17 '15 at 12:27
  • 1
    Thanks. My saga has finally come to an end. in ~/.bashrc I have : alias gitssh='eval ssh-agent -s && ssh-add ~/.ssh/id_rsa' . And with that, its finally working the way I want it to. Thanks for the help. :) – Click Upvote Mar 19 '15 at 13:18
12

Another alternative is to add this to your .bashrc. This has the same advantage as Erik's answer (ensuring a single instance) but doesn't require an additional package.

# SSH Agent should be running, once
runcount=$(ps -ef | grep "ssh-agent" | grep -v "grep" | wc -l)
if [ $runcount -eq 0 ]; then
    echo Starting SSH Agent
    eval $(ssh-agent -s)
fi

This runs ssh-add if there is not at least 1 key loaded and sets a key timeout of 1 day:

ssh-add -l &>/dev/null
if ! [ "$?" == 0 ]; then
     echo Adding keys...
     ssh-add -t 1d
fi
  • 1
    If ssh-agent is already running, but without any keys loaded, this doesn't call ssh-add. Better add another condition and check the output of ssh-add -l - if it is >0, run something like ssh-add -t 4h – squarespiral Dec 26 '21 at 15:54
9

One alternative is to use Funtoo's Keychain. Then you can stick this one-liner in your bash shell:

eval $(keychain --eval id_rsa)

That does the same thing (launches ssh agent, etc.), while also not running an ssh-agent process for each subshell. Instead it looks for "already running" instances you own and attaches you to them.

Matt
  • 322
  • 2
  • 3
  • 12
2

Same answer as @womblerone, but a little bit slimmer:

Run the ssh agent (if not already running):

# SSH Agent should be running, once
if ! ps -ef | grep "[s]sh-agent" &>/dev/null; then
    echo Starting SSH Agent
    eval $(ssh-agent -s)
fi

Add the ssh-key if no keys are added yet

if ! ssh-add -l &>/dev/null; then
     echo Adding keys...
     ssh-add -t 1d
fi
guenhter
  • 131
1

Also keep in mind if you have ssh connection keep-alive you need to delete existing connection files before -A takes effect. Delete any ssh connection files in /tmp/[host].

Soheil
  • 111
1

If you used both zsh (Oh-my-zsh) and bash I have written this this little script that is compatible with it.

SHORT_HOST="${HOSTNAME/.*/}"
ssh_env_cache="$HOME/.ssh/environment-$SHORT_HOST"

Oh-my-zsh compatible bash ssh-agent start script

function _start_agent() { if [[ -f "$ssh_env_cache" ]]; then . "$ssh_env_cache" > /dev/null fi

if [[ -S "$SSH_AUTH_SOCK" ]]; then
  return 0
fi

echo "Starting ssh-agent ..."
ssh-agent -s | sed '/^echo/d' > "$ssh_env_cache"
chmod 600 "$ssh_env_cache"
. "$ssh_env_cache" > /dev/null

} _start_agent

unset ssh_env_cache unset -f _start_agent

ssh-add ~/.ssh/id_rsa

On the plus side this will prevent spawning another ssh-agent every time you start a bash session.

Fuxy
  • 11