83

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
  • Why key agent on the server? It should be on your local client that you are connecting from. Commented Mar 2, 2015 at 5:49
  • @Zoredache I want to be able to do git pull and such on the remote server Commented Mar 2, 2015 at 16:21
  • 2
    Then run an SSH agent on your local machine, and forward the agent. Commented 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. Commented 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? Commented Jan 4, 2022 at 22:40

8 Answers 8

89

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? Commented 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 ... Commented 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 Commented Mar 12, 2015 at 23:15
  • 1
    you could create an alias Commented 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. :) Commented Mar 19, 2015 at 13:18
16

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.

14

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 
4
  • 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 Commented Dec 26, 2021 at 15:54
  • 1
    On a multi-user system, should it be ps -fu "$USER"? For me, this snippet finds another user's ssh-agent, which isn't helpful. Commented Apr 30 at 19:35
  • Wait, this doesn't work the same as keychain. If ssh-agent is already running, you don't export its environment variables, so ssh-add and ssh won't use it. Commented Apr 30 at 19:47
  • @Jacktose it does export. Look at the output of ssh-agent -s (just run it and see). For me this includes exports for SSH_AUTH_SOCK and SSH_AGENT_PID These are the commands that are getting eval'd. Commented yesterday
6

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 
3
  • On a multi-user system, should it be ps -fu "$USER"? For me, this snippet finds another user's ssh-agent, which isn't helpful. Commented Apr 30 at 19:35
  • Wait, this doesn't work the same as keychain. If ssh-agent is already running, you don't export its environment variables, so ssh-add and ssh won't use it. Commented Apr 30 at 19:47
  • It does export, as I noted elsewhere. Run ssh-agent -s to see what is getting eval'd. Commented yesterday
5

A clean way to start the ssh-agent would be systemd: https://gist.github.com/magnetikonline/b6255da90606fe9c5c25d3333c98c90d

add the following to your ~/.bashrc or ~/.zshrc

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" if ! ssh-add -l &>/dev/null; then echo Adding keys... ssh-add -t 1d ~/.ssh/id_rsa fi 

logout and log back in

create the file /etc/systemd/user/ssh-agent.service with these contents:

[Unit] Description=SSH authentication agent [Service] ExecStart=/usr/bin/ssh-agent -a %t/ssh-agent.socket -D Type=simple [Install] WantedBy=default.target 

and execute this command with your user account:

systemctl --user enable --now ssh-agent 

check if it worked:

ssh-add -Lexport SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" 

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

2

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.

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

0

If you want to unlock the key:

  1. no more than once per login
  2. on-demand (i.e. when you actually are trying to use the key)

You can do the following (tested on Ubuntu):

apt install keychain 

in your .bashrc/.zshrc add:

eval $(keychain --eval --quiet) 

Note that unlike in many other answers on StackExchange, we do not specify any keys in this step. Keychain only makes sure the one and only one instance of the ssh-agent is started.

Then, in your .ssh/config add AddKeysToAgent yes. This loads the key into the ssh-agent the first time we use it. Your config should thus look something like this:

Host * AddKeysToAgent yes Host my-server HostName example.com IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.