I've written a few articles now regarding my SSH setup and my .bashrc
and
.bash_profile
files. I think I finally arrived at a configuration that's good,
and I'd like to share my findings.
This is the complete content of my ~/.bash_profile
:
# if a directory exists, add it to $PATH
__add_path_head() {
if [ -d "$1" ]; then
if [ -n "${PATH}" ]; then
PATH="$1:${PATH}"
else
PATH="$1"
fi
fi
}
export PATH
__add_path_head "${HOME}/local/bin"
__add_path_head "${HOME}/local/sbin"
__add_path_head "${HOME}/opt/arcanist/bin"
export GOPATH="${HOME}/gocode"
if [ ! -d "${GOPATH}/bin" ]; then
mkdir -p "${GOPATH}/bin"
fi
__add_path_head "${GOPATH}/bin"
# Try to find an already running ssh-agent process
foundagent=0
for agentsock in $(find /tmp/ssh-* -name 'agent.*' -type s 2>/dev/null); do
export SSH_AUTH_SOCK="${agentsock}"
ssh-add -l &>/dev/null
# 0 means the agent had keys, 1 means the agent is properly configured but
# has no keys, 2 would mean that the SSH_AUTH_SOCK is inavlid
if [ $? -lt 2 ]; then
foundagent=1
break
fi
done
# If no ssh-agent process was found, create a new one
if [ "${foundagent}" -eq 0 ]; then
source <(ssh-agent)
fi
# source .bashrc if we're on a tty
test -t 0 && source ~/.bashrc
The relevant points are:
- I set up
PATH
correctly for my locally installed and Go programs - I find any existing
ssh-agent
process that can be connected to - I start an
ssh-agent
process if there is no connectable process running - if stdin is a TTY then I source
~/.bashrc
The code that I have for detecting an SSH agent is not comprehensive; it assumes
that you're using the actual ssh-agent
program that puts agent sockets in a
predictable place. If you want something that handles more edge cases (e.g. OS X
or the GNOME keyring) Wayne Walker has a project on Git Hub called
ssh-find-agent which can handle
those cases (but is a lot more complicated).
If you paid close attention you may have noticed that no SSH keys are
automatically loaded. You can sort of do this with
pam_ssh or
gnome-keyring but AFAIK
neither supports the new SSH protocol 2 private keys (i.e. as generated by
ssh-keygen -o
), and gnome-keyring has other bugs that I've blogged about
earlier (e.g. you can't remove keys from it).
I also want my SSH encryption key to be different from my login password, and
AFAIK pam_ssh
requires that the two be the same.
Instead what I do is have some wrapper methods in my ~/.bashrc
that load keys
into my ssh-agent
the first time the key is used. The relevant code from my
'~/.bashrc` file is like:
ensure_ssh() {
/usr/bin/ssh-add -l &>/dev/null || /usr/bin/ssh-add
}
ssh() {
ensure_ssh
/usr/bin/ssh "$@"
}
rsync() {
ensure_ssh
/usr/bin/rsync "$@"
}
unset SSH_ASKPASS
The first time I run ssh
or rsync
I'm prompted for a key and then it is
loaded into my agent. I also unset SSH_ASKPASS
as I dislike the graphical SSH
password manager that GNOME sets during login.