357

I want to communicate between several computers on my network (static Ethernet), through SSH. In order to do that I need to run ssh-add every time I log in on a specific machine.

What can I do so it's set up once and it doesn't ask me for the passphrase every time I log in or reboot my machine?

I know that there is a way where you add some lines to the bash_profile file, but I still need to type the password every time I reboot/log in to a specific machine.

if [ -z "$SSH_AUTH_SOCK" ] ; then
    eval `ssh-agent -s`
    ssh-add
fi
3

23 Answers 23

483

This is a typical example of a trade-off between security and convenience. Luckily, there are a number of options. The most appropriate solution depends on the usage scenario and desired level of security.

ssh-key with passphrase, no ssh-agent

Now the passphrase has to be entered every time the key is used for authentication. While this is the best option from a security standpoint, it offers the worst usability. This may also lead to a weak passphrase being chosen in order to lessen the burden of entering it repeatedly.

ssh-key with passphrase, with ssh-agent

Adding the following to ~/.bash_profile will automatically start ssh-agent and load the ssh-key(s) on login:

if [ -z "$SSH_AUTH_SOCK" ] ; then
  eval `ssh-agent -s`
  ssh-add
fi

Now the passphrase must be entered upon every login. While slightly better from a usability perspective, this has the drawback that ssh-agent prompts for the passphrase regardless whether the key is to be used or not during the login session. Each new login also spawns a distinct ssh-agent instance which remains running with the added keys in memory even after logout, unless explicitly killed.

To kill ssh_agent on logout, add the following to ~/.bash_logout

if [ -n "$SSH_AUTH_SOCK" ] ; then
  eval `/usr/bin/ssh-agent -k`
fi

or the following to ~/.bash_profile

trap 'test -n "$SSH_AUTH_SOCK" && eval `/usr/bin/ssh-agent -k`' 0

Creating multiple ssh-agent instances can be avoided by creating a persistent communication socket to the agent at a fixed location in the file system, such as in Collin Anderson's answer. This is an improvement over spawning multiple agents instances. However, unless explicitly killed, the decrypted key still remains in memory after logout.

On desktops, ssh-agents included with the desktop environment, such as the Gnome Keyring SSH Agent, can be a better approach as they typically can be made to prompt for the passphrase the first time the ssh-key is used during a login session and store the decrypted private key in memory until the end of the session.

ssh-key with passphrase, with ssh-ident

ssh-ident is a utility that can manage ssh-agent on your behalf and load identities as necessary. It adds keys only once they are needed, regardless of how many terminals, SSH or login sessions require access to an ssh-agent. It can also add and use a different agent and different set of keys depending on the host you are connected to, or the directory ssh is invoked from. This allows for isolating keys when using agent forwarding with different hosts. It also allows using multiple accounts on sites like GitHub.

To enable ssh-ident, install it and add the following alias to your ~/.bash_profile:

alias ssh='/path/to/ssh-ident'

ssh-key with passphrase, with keychain

keychain is a small utility which manages ssh-agent on your behalf and allows the ssh-agent to remain running when the login session ends. On subsequent logins, keychain will connect to the existing ssh-agent instance. In practice, this means that the passphrase must be be entered only during the first login after a reboot. On subsequent logins, the unencrypted key from the existing ssh-agent instance is used. This can also be useful for allowing passwordless RSA/DSA authentication in cron jobs without passwordless ssh-keys.

To enable keychain, install it and add something like the following to ~/.bash_profile:

eval `keychain --agents ssh --eval id_rsa`

From a security point of view, ssh-ident and keychain are worse than ssh-agent instances limited to the lifetime of a particular session, but they offer a high level of convenience. To improve the security of keychain, some people add the --clear option to their ~/.bash_profile keychain invocation. By doing this, passphrases must be re-entered on login as above, but cron jobs will still have access to the unencrypted keys after the user logs out. The keychain wiki page has more information and examples.

ssh-key without passphrase

From a security standpoint, this is the worst option since the private key is entirely unprotected in case it is exposed. This is, however, the only way to make sure that the passphrase need not be re-entered after a reboot.

ssh-key with passphrase, with ssh-agent, passing passphrase to ssh-add from script

While it might seem like a straightforward idea to pass the passphrase to ssh-add from a script, e.g. echo "passphrase\n" | ssh-add, this is not as straightforward as it seems as ssh-add does not read the passphrase from stdin, but opens /dev/tty directly for reading.

This can be worked around with expect, a tool for automating interactive applications. Below is an example of a script which adds a ssh-key using a passphrase stored in the script:

#!/usr/bin/expect -f
spawn ssh-add /home/user/.ssh/id_rsa
expect "Enter passphrase for /home/user/.ssh/id_rsa:"
send "passphrase\n";
expect "Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)"
interact

Note that as the passphrase is stored in plaintext in the script, from a security perspective, this is hardly better than having a passwordless ssh-key. If this approach is to be used, it is important to make sure that the expect script containing the passphrase has proper permissions set to it, making it readable, writable, and runnable only by the key owner.

19
  • 1
    Okay, but when I put your code to ~/.bash_profile I have to type in password every time I login, I don't want that either. I am not concerned about security at all. echo "pass\n" | ssh-add doesn't work
    – zdun8
    Commented Sep 17, 2013 at 12:59
  • 3
    @user1607072 Yeah, that is how the ssh-agent snippet in ~/.bash_profile behaves as explained in the answer. You might want to look at the keychain utility. With keychain you need to enter the password on first login after reboot, but on subsequent logins keychain will connect to an existing ssh-agent instance with the decrypted key in memory. Apart from that there's the option of generating a ssh-key without a passphrase, but this is of course not recommended. Commented Sep 17, 2013 at 13:35
  • 3
    @user1607072 While I would strongly suggest one of the more secure approaches, there is a way to pass the passphrase to ssh-add from a script. The reason echo "pass\n" | ssh-add does not work is that ssh-add does not read the password from stdin, but opens /dev/tty directly for reading. Updated the answer to include a workaround for this, using an utility called expect. Commented Sep 17, 2013 at 18:03
  • 1
    @user1607072 It might be a bit overkill for your use case, but Kerberos in combination with ssh GSSAPI support can also be used for passwordless ssh logins. The corresponding authentication method in ssh is called gssapi-with-mic. This is usually used in larger networks, but of course if you have interest in this it might be worth looking into. Commented Sep 18, 2013 at 11:54
  • 1
    @ErickBrown: Already answered here. The SSH Agent unit should be stopped on logout if you have user lingering disabled in the systemd login manager. If user lingering is enabled, the systemd user instance and the SSH Agent unit are kept running even after the last login session is closed. Commented Jul 25, 2018 at 8:00
156

Add this to your ~/.bashrc, then log out and back in to take effect.

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
  eval `ssh-agent`
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add

This should only prompt for a password the first time you log in after each reboot. It will keep reusing the same ssh-agent as long as it's running.

16
  • 3
    very neat, this way you only have one ssh-agent running (: Multiple agents as in @thomasNyman's second solution seems a security risk to me...
    – drevicko
    Commented Feb 10, 2016 at 11:54
  • 3
    better to do this: `alias ssh=ssh-check-agent", and have the check-agent version do the above. that way: a) you only get one agent and b) you only get the agent if you need it Commented Jul 26, 2016 at 20:31
  • 3
    I think -s is the default, so we're already doing that. Commented Nov 22, 2016 at 16:25
  • 14
    Note that ssh-add without arguments adds ~/.ssh/id_rsa. You might want to pass ssh-add arguments if your private keys are in another file. Commented Nov 1, 2019 at 13:54
  • 3
    @cprn Ah, so the assumption is that /tmp is in memory. That explains. On Git Bash on Windows, /tmp is mapped to C:\Users\<username>\AppData\Local\Temp which is a location on disk (afaik) and the socket is not deleted. I've since added ps | grep ssh-agent > /dev/null || rm ~/.ssh/ssh_auth_sock > /dev/null 2>&1 to my ~/.bashrc to remove the symlink. Sounds like I still/instead should clean up the socket file itself then.
    – tjalling
    Commented Dec 16, 2020 at 8:59
38

Not closely related to the OP's question, but it might be useful to others: since 7.2.0, ssh has an option that allows adding a key to ssh-agent upon first authentication; the option is AddKeysToAgent and can be set to yes, no, ask, or confirm, system-wide or in your personal .ssh/config file.

4
  • 4
    Applicable to those who are new to the .ssh/config file: this applies to ssh and anything that uses ssh behind it, for example scp, and can be done on a per-host basis.
    – SEoF
    Commented Sep 25, 2017 at 14:32
  • 2
    It still asks me for password each time I login and try to git pull for example.
    – trainoasis
    Commented Aug 7, 2019 at 10:15
  • 1
    @trainosis The issue is that you probably do not have an ssh-agent instance running to hold the decrypted key(s) in memory for future use. You should only need to enter the password for a given key once per login session when using ssh-agent.
    – eestrada
    Commented Aug 13, 2019 at 20:43
  • also note that this can be applied in conjunction with other answers like unix.stackexchange.com/a/217223/355088 by just removing the ssh-add part
    – CervEd
    Commented Feb 3, 2023 at 8:48
11

ssh-agent caches various unlocked ssh-keys, so you can have ssh-keys protected by passwords, but without having to type them every single time.

In order to cache unlocked keys, it obviously needs to unlock those keys. For unlocking keys that are locked with a passphrase, it obviously needs to know these passphrases.

Any method that does not require authorization from a human being (e.g. "typing in a password") will not only make your system insecure; it will also render the entire purpose of the ssh-agent meaningless.

Having said all this, you can simply use ssh-keys that are not password protected (hit Enter when asked for a password during key-generation). Since there isn't any password, ssh-agent doesn't need to ask you for one in order to (not) cache it.

1
  • 1
    I agree, as long as your keys are properly user-only-permissioned, there is little advantage to ssh-agent over permissionless keys. i like to ssh into a login server, and then, that server has a bunch of permssionless keys, each of which can only be used to unlock one other server. the login server does nothing else, so it's much harder to hack/spoof, etc... the other servers have no password access, are key-only. Commented Jul 26, 2016 at 20:34
10

Here is a workaround to automate your SSH passphrase.

  1. Create a one-liner script which prints your passphrase to standard output, e.g.:

     echo 'echo MY_SSH_PASSWORD' > ~/.print_ssh_password && chmod 700 ~/.print_ssh_password
    

    Important: Ensure you copy the leading space to prevent storing your password to your history.

And use one of the below methods.

  • using a standard input approach:

    cat ~/.ssh/id_rsa | SSH_ASKPASS=~/.print_ssh_password ssh-add -
    
  • or named pipe approach:

    1. Create a named pipe (you could also try a process substitution):

      mkfifo --mode 0600 ~/.ssh_fifo
      
    2. Run ssh-add by specifying the program used for the authentication:

      cat ~/.ssh/id_rsa >~/.ssh_fifo | SSH_ASKPASS=~/.print_ssh_password ssh-add ~/.ssh_fifo
      

    See: man ssh-add to read more about SSH_ASKPASS.

3
  • 4
    The echo my_passphrase is a big security hole. First after you have typed it, the password is in clear text in the history file of what ever shell you use. And second command line arguments are world readable on Unix (ps -ef). Never put passwords in command line arguments!
    – ceving
    Commented Aug 24, 2016 at 9:03
  • 2
    @ceving Adding extra leading space solves the problem with the history file. Added extra info.
    – kenorb
    Commented Aug 24, 2016 at 9:25
  • 1
    @kenorb: That doesn't solve the bigger problem of the password visible in ps output. The history file is typically only readable by the owning user anyway, but the command lines are readable by all users on a system. Commented Nov 23, 2016 at 14:37
6

I won't recommend you ssh-add (which need to open a ssh-agent) at login. This is because you can't control when the ssh-agent section ends, and can create security risk when you need not use the keyfiles at one login section.

Rather, I recommend to write a script which opens a ssh-agent's section sub-shell, with all keyfiles auto added, and be called when needed to use ssh. If you could adopt so, read on.

You would have two choices:

  1. Remove all passphrases for your keys, which have weak security if your key files are stolen. (thus not recommended)

  2. Use the same passphrase for your keys. Then when you ssh-add keyfile1 keyfile2 ..., you will only need to type the passphrase once, per section.

In both cases, you could write such script file "ssh_keys_section.sh" as below:

#!/bin/bash
# This script run a ssh-agent on a sub-shell and automatically ssh-add all keyfiles at once.
# This agent ends when you type `exit` to close the sub-shell.
exec ssh-agent bash -c "ssh-add /path/to/keyfile1 /path/to/keyfile2 ...; exec bash"

Remarks:

  • Command to change or delete passphrase: ssh-keygen -p -f keyfile
  • Within the sub-shell, you might even fork more terminals which share the same unlocked keys, by using maybe a command like /path/to/yourterminal & (depends on OS)
2
  • E.g. On Windows within Cygwin, /path/to/yourterminal & ==> mintty & Commented Mar 25, 2019 at 9:50
  • Remark: after use, close the session with ctrl-d or exit, just like you have invoked a nested bash shell and need to close it. Commented Nov 1, 2019 at 8:44
3

If you are running seahorse as your password manager ... Which you probably are ;D

Another solution that achieves the goal you are looking for is simply adding the ssh keys to seahorse for automatic unlock upon login. The major benefit to this is that you never have to enter a password for the keys after you login through gdm, or whatever your loging in with even if the keys have a password. This REQUIRES both the private key and the public key. They also MUST follow a naming convention for seahorse. The default is acceptable (id_rsa for private key and id_rsa.pub for public key... Really anything that is privatekeyname and privatekeyname.pub)

To add you ssh key to seahorse for automatic unlock upon login; (on fedora25, I'm not sure where the path is on other distros though its most likely very similar)

/lib64/seahorse/seahorse-ssh-askpass /path/to/keys/here

For me, it was

/lib64/seahorse/seahorse-ssh-askpass ~/.ssh/id_rsa

(seahorse will automatically assume that the public key in my case was id_rsa.pub)

After executing the command, seahorse will pop open a cute little gtk password field to enter the password for the private key into. or just leave it blank if you generated the key without a password.

Seahorse won't prompt you if everything went okay. You will need to attempt to ssh into the target machine. Then seahorse will prompt you to unlock the key with a password graphically (THIS WILL ONLY HAPPEN ONCE) again but it should look a little different this time ;P (this is also the part where seahorse does some seahorse to ssh-add magic I believe), and offer the OPTION to unlock the key upon login, you must check this option to achieve your goal.

Just because I didn't read all the answers, I would recommend undoing what everyone told you to do with ssh-add before attempting this answer. Doing so otherwise might result in something bad happening to your keys, idk.

3

I used to use the script mentioned by steampowered, I've made the below one now, because it doesn't leave files lying around.

Working on zsh shell only.

#!/usr/bin/env zsh

AGENT_BIN=`which ssh-agent`
AGENT_ADD_BIN=`which ssh-add`
AGENT_PID=`ps -fe | grep ${AGENT_BIN} | awk -vuser=$USER -vcmd="$AGENT_BIN" '$1==user && $8==cmd{print $2;exit;}'`
if [ -z "$AGENT_BIN" ]; then
    echo "no ssh agent found!";
    return
fi
if [ "" -eq "$AGENT_PID" ]; then
    if read -sq "YN?Do you want to unlock your ssh keys?"; then
        echo ""
        output=`$AGENT_BIN | sed 's/echo/#echo/g'`
        eval $output
        $AGENT_ADD_BIN
    fi
else
    for f in "/proc/"*
    do
        cmdline=`cat "$f/cmdline"`
        if [ "${AGENT_BIN}" -ef "${cmdline}" ]; then
            export SSH_AUTH_SOCK=`cat $f/net/unix | grep --binary-file=text -oP '((/[^/]*?)+/ssh-[^/]+/agent\.\d+$)'`
            export SSH_AGENT_PID=${f##*/}
            break;
        fi
    done
fi
0
2
SSH_ENV="$HOME/.ssh/environment"

function start_agent {
     echo "Initialising new SSH agent..."
     /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
     echo succeeded
     chmod 600 "${SSH_ENV}"
     . "${SSH_ENV}" > /dev/null
     /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
     . "${SSH_ENV}" > /dev/null
     #ps ${SSH_AGENT_PID} doesn't work under cywgin
     ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
         start_agent;
     }
else
     start_agent;
fi

Giving credit here: https://www.cygwin.com/ml/cygwin/2001-06/msg00537.html

This solution is also endorsed here: http://mah.everybody.org/docs/ssh

0
2
if [ ! -S ${HOME}/.ssh/ssh_auth_sock ]; then
  eval $(ssh-agent)
  ln -sf "${SSH_AUTH_SOCK}" ${HOME}/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=${HOME}/.ssh/ssh_auth_sock

ssh_keys=$(find -E ~/.ssh -type f -regex '.*(rsa$|pem)')
ssh_agent_keys=$(ssh-add -l | awk '{key=NF-1; print $key}')

for k in "${ssh_keys}"; do
    for l in "${ssh_agent_keys}"; do
        if [[ ! "${k}" = "${l}" ]]; then
            ssh-add "${k}" > /dev/null 2>&1
        fi
    done
done
1
  • Description is encouraged
    – CervEd
    Commented Jan 27, 2023 at 10:06
2

Single sign on solution for SSH could lead me to pam_ssh.

According to this article, the concept is:

If you work with multiple *nix-based machines via ssh, you are probably tired of constantly having to enter your password every time you want to access another box. There is a secure way to allow you to access every machine, that you have ssh access to, without having to enter another password (other than the one you signed on with originally.)


This is actually quite simple to do, you basically just create a public/private key pair to authenticate yourself to your other machines, then have PAM spawn an agent to load your keys after you logon, providing a single signon solution to accessing all your remote machines. This guide will walk you through setting this up.

I have not verified this would actually work.

2

Inspired by Collin Anderson's answer, I wrote an alternative script (that needs to be put inside of your .bashrc file) which unlike his, actually works in an environment like WSL (where the /tmp directory doesn't get cleared, which is what his solution relies on):

source ~/.ssh/agent_out &> /dev/null
if ! ps -p $SSH_AGENT_PID &> /dev/null
then
  ssh-agent > ~/.ssh/agent_out
  source ~/ssh/agent_out &> /dev/null
fi

To understand what this script is actually doing, let’s consider what it would do the first time it’s run:

  1. It spins up an SSH agent, stores the output of the ssh-agent command inside a file called agent_out in the user’s .ssh directory for later use. The output of the ssh-agent command contains statements to assign the right values to environment variables like SSH_AUTH_SOCK and SSH_AGENT_PID.
  2. For every new shell session, it first executes the output of the last ssh-agent command which was stored in the ~/.ssh/agent_out file, and then checks whether the process with the ID included in SSH_AGENT_PID actually exists or not. If it doesn’t, it performs the first step.

This, coupled with the new SSH config option AddKeysToAgent — see the manual —, would yield a nice user experience, and eliminate the need for third-party tools like keychain and ssh-ident for the most part:

~/.ssh/config:

AddKeysToAgent yes
1
  • What if the PID is taken by another process that is not ssh-agent?
    – trallnag
    Commented Aug 5, 2022 at 14:12
1

My setup on macOS is as follow (in .zshrc, or .bash_profile for bash folks):

# Kill then Load the ssh-agent and set the necessary env variables it outputs
sshRestart() {
    # if all else fails
    # pkill -u $(whoami) ssh-agent;

    if [ -n "$SSH_AUTH_SOCK" ] ; then
        eval `/usr/bin/ssh-agent -k`
    fi
    eval `ssh-agent -s`
    ssh-add ~/.ssh/YOUR_KEY_FILE
    echo "Restarted SSH agent"
}

if [ -z "$SSH_AUTH_SOCK" ] || [[ $SSH_AUTH_SOCK == *"/private/tmp/"* ]] ; then
    eval `ssh-agent -s` > /dev/null 2>&1
    ssh-add ~/.ssh/YOUR_KEY_FILE > /dev/null 2>&1
fi

The || [[ $SSH_AUTH_SOCK == *"/private/tmp/"* ]] part is necessary on macOS because the default value is /private/tmp/com.apple.launchd.SOMETHINGHERE/Listeners. Otherwise @Thomas Nyman comprehensive answer fails because $SSH_AUTH_SOCK is always set to something.

Then in .zlogout (or .bash_logout for bash folks):

if [ -n "$SSH_AUTH_SOCK" ] ; then
    eval `/usr/bin/ssh-agent -k`
fi

Tested on macOS Mojave 10.14.5

1

This has been very well explained by GitHub on Auto-launching ssh-agent on Git for Windows, which in turn works for Linux also.

You can run ssh-agent automatically when you open bash or Git shell. Copy the following lines and paste them into your ~/.profile or ~/.bashrc file in Git shell:

env=~/.ssh/agent.env

agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }

agent_start () {
    (umask 077; ssh-agent >| "$env")
    . "$env" >| /dev/null ; }

agent_load_env

# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2= agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)

if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
    agent_start
    ssh-add
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
    ssh-add
fi

unset env

If your private key is not stored in one of the default locations (like ~/.ssh/id_rsa), you'll need to tell your SSH authentication agent where to find it. To add your key to ssh-agent, type ssh-add ~/path/to/my_key.

Tip: If you want ssh-agent to forget your key after some time, you can configure it to do so by running ssh-add -t <seconds>.

1

The easiest solution does not have to be bad.

You need neither ssh-agent nor ssh-add when you use a passwordless private key, see https://stackoverflow.com/a/48290333/11154841.

That does not need to be insecure: you simply need to delete both keys of the key pair right after their usage. That means, you must delete the public key on the server and delete the private key on the client. It goes without saying: never use them again, do not even keep a backup somewhere.

Mind that you can create the public key from a private key, but not the other way round. Normally, it should suffice to simply delete the public key from the registered keys on your Git portal, but they should better be both deleted, so that the same public key can never ever be used again. Even if someone had stolen your private key, it would be of no use if you simply never use its public key again.

With a passwordless private key, you can even use it in Docker to get around any password entries. You can clone a git repo without any password, the passwordless private key is all you need. See Dockerfile: clone repo with passwordless private key. Errors: “authentication agent” or “read_passphrase: can't open /dev/tty” as an example.

4
  • I guess using a new key pair every time will be much more hassle than entering a password.
    – EvgenKo423
    Commented Jul 7, 2021 at 12:27
  • @EvgenKo423 You are right, obviously. But if you are not allowed to use pw security, or if you use dockerfile which does not accept console entries when running, then this helps. There is also another approach to use a deployment token, then you do not need to upload your own private key, but you use just the command including the token, then. This is a once-off effort but not that secure anymore if that token gets spread. Commented Jul 7, 2021 at 12:50
  • But using an ssh agent anyway has other advantages such as agent forwarding
    – tbrugere
    Commented Jun 30, 2022 at 10:00
  • @Nephanth It might be the easiest solution here, but not the best. The only good use case is if you need to get docker to run through without any console action. in such cases, you would need a trick like this (linked above). Without Docker, you are better off with the ssh agent. Commented Jun 30, 2022 at 16:22
1

I really like this answer by @Collin Anderson, and I upvoted it. I then added a modified version of it to my personal ssh documentation here. Among my changes are print statements to explain what's going on, and an if statement to replace this line (ssh-add -l > /dev/null || ssh-add) to make it more clear what's really happening.

Here is my version below.

Description:

Auto-start the ssh agent and add necessary keys once per reboot.

This is recommended to be added to your ~/.bash_aliases (preferred) or ~/.bashrc file on any remote ssh server development machine that you generally ssh into, and from which you must ssh into other machines or servers, such as to push code to GitHub over ssh. If you only graphically log into this machine, however, there is no need to do this, as Ubuntu's Gnome window manager, for instance, will automatically start and manage the ssh-agent for you instead.

Code:

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
    echo "'ssh-agent' has not been started since the last reboot." \
         "Starting 'ssh-agent' now."
    eval "$(ssh-agent -s)"
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
# see if any key files are already added to the ssh-agent, and if not, add them
ssh-add -l > /dev/null
if [ "$?" -ne "0" ]; then
    echo "No ssh keys have been added to your 'ssh-agent' since the last" \
         "reboot. Adding default keys now."
    ssh-add
fi
1

Not recommend but you could just remove the password outright with:

ssh-keygen -p

Then leave the new password blank

0

Add this to your ~/.bashrc file:

ssh-add -L|grep identities > /dev/null && ssh-add /path/to/ssh/private/key
1
  • 2
    I don't see how this relates to the question, which is about not being prompted for the password on subsequent logins.
    – Chris Down
    Commented Jan 6, 2014 at 13:23
0

In order to add a (possibly passwordless) key and ensure that ssh-add will not prompt for a password, no matter what, even when running under X:

DISPLAY= ssh-add -k /path/to/key </dev/null &>/dev/null

Exit status indicates success or failure.

0

The best way I am aware of is to use a PAM login script I adapted from previous work because I couldn't find a satisfying answer in this question.

Your passphrase gets stored encrypted with your system password and a heavy derivation function. At login, your system password is used to decrypt your passphrase and add it to the agent.

https://github.com/capocasa/systemd-user-pam-ssh

The advantage over every other solution presented is that it combines security equivalent to running ssh-add manually at boot with zero effort. It requires no extra tools and has one extra dependency that's already installed by default on most systems (OpenSSL).

0

Answering as a future note for myself: on Fedora do nothing! Simply pull git repository with this key. Then gui will popup and ask you whether to store it in keyring. Now you can use this key automatically after login.

0

It's possible to do this securely if you have a decent password manager.

Using a variation of albfan's answer to a different question, we trick ssh-add into accepting input from stdin by using setsid, as well as setting the DISPLAY and SSH_ASKPASS variables. The latter is set to the path of a script that echos the password.

% cat > add_key.sh <<EOF
#!/bin/zsh
export DISPLAY
export OP_SERVICE_ACCOUNT_TOKEN
DISPLAY=dummy
export SSH_ASKPASS="./echo_op.sh"
setsid ssh-add /home/foo/.ssh/path/keyfile < /dev/null
EOF

And in echo_op.sh, you refer to your password manager (in this case, 1Password and its command-line tool, op):

#!/bin/zsh
echo $(op read "op://VaultName/EntryName/SectionName/PasswordFieldName")

To add the key, call ./add_key.sh.

If someone with better shell knowledge could suggest a way to make this more flexible via passed arguments (key paths, for instance), that would be appreciated.

-1

Here is the definitive script.

Update $PASSW, then copy-paste it in your Terminal

# <sshpass> via typinator
# Updated: 2017-01-18_21h36
#
# apt-get update -y; apt-get install expect -qy

# Pass this value to ssh-add
PASSW="myfancypass123"

# Define a name for this script
THIS_SCRIPT="$(date +%Y-%m-%d_%H-%M-%S-%N)".sh

# Create a fresh directory to work from / Clean up
rm -rf ~/temp; mkdir -p ~/temp; cd ~/temp; ls -la


# Output our bash script file - BEGIN
cat <<< '
#!/bin/bash

set -u     # Stop if an unbound variable is referenced
set -e     # Stop on first error
export HISTIGNORE="expect*";

# Normal CMDs
echo && echo "The process should take about 10 seconds:" && echo
eval "$(ssh-agent -s)"; sleep 0.5;

# Define VAR passed when this bash-script was launched
password="$@"

# Launch the expect magic
expect -c "
    spawn ssh-add /root/.ssh/id_rsa
    expect "?assword:"
    send \"$password\r\"
    expect "?password:"
    send \"$password\r\"
    expect eof"

export HISTIGNORE="";
export password="";
' > $THIS_SCRIPT
# Output our bash script file - END


# Ensure we are in the right path
cd ~/temp; ls -la; sleep 1;

# Run the bash script
chmod +x ./$THIS_SCRIPT; ./$THIS_SCRIPT "$PASSW"; unset password;

# Clean up
rm -rf ~/temp; mkdir -p ~/temp; cd ~/temp; ls -la
0

You must log in to answer this question.

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