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

5
  • Why key agent on the server? It should be on your local client that you are connecting from.
    – Zoredache
    Mar 2, 2015 at 5:49
  • @Zoredache I want to be able to do git pull and such on the remote server Mar 2, 2015 at 16:21
  • 1
    Then run an SSH agent on your local machine, and forward the agent.
    – Zoredache
    Mar 2, 2015 at 17:39
  • @Zoredache Thanks, didn't know that was possible. However I'd still like to be able to do ssh-add / ssh-agent from within a bash script, even from my local machine. Its a pain to have to run those commands manually. Mar 3, 2015 at 8:39
  • This is a fantastic answer and works perfectly! It requires typing your ssh keys only once per reboot of your remote server: Unix & Linux: How can I run ssh-add automatically, without a password prompt? Jan 4, 2022 at 22:40

6 Answers 6

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.

20
  • 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? Mar 3, 2015 at 8: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 ... Mar 3, 2015 at 11:09
  • 1
    oops just realised in bash you need an extra eval in front of the ssh-agent call .. updated my answer above Mar 12, 2015 at 23:15
  • 1
    you could create an alias Mar 17, 2015 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. :) Mar 19, 2015 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
  • 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 Dec 26, 2021 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.

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
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].

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .