When I first started using Debian properly, I played with gpg-agent
and pinentry
but I didn’t really understand the various bash initialisation scripts, and my botched setup annoyed me so much I disabled it again quite quickly (for example, if I left the machine logged in to GDM at home then logged in through SSH, pinentry dialogs stayed in GDM and had to be killed).
Now I’ve finally had time to get it sorted out, and this is part aide-memoire and part idiot check (hello, lazyweb). The brief:
gpg-agent
should take care of both GPG keys and SSH keys, transparently;pinentry
should ask withpinentry-gtk2
at home, or at the current SSH session remotely;- nothing should be left lying around after a session.
I assume appropriate packages are already installed – at a minimum, gpg-agent
and whichever pinentry
you prefer.
Installing gpg-agent
drops a hook into /etc/X11/Xsession.d
, but now there are both gpg-agent
and ssh-agent
running. Disable ssh-agent
because we’re going to let gpg-agent
take care of everything: in /etc/X11/Xsession.options
, comment out the line use-ssh-agent. In /etc/X11/Xsession.d/90gpg-agent
, add the –enable-ssh-support parameter so the STARTUP variable looks something like:
STARTUP="$GPGAGENT --daemon --sh --enable-ssh-support --write-env-file=$PID_FILE $STARTUP"
and also disable ssh in gnome-keyring
:
$ gconftool-2 --set -t bool /apps/gnome-keyring/daemon-components/ssh false
Now (after restarting your X session) you can use ssh-add to import a key into gpg-agent
, and you should see a pinentry dialog asking for a password.
That takes care of X sessions, but it won’t work for SSH. This is where the different bash login scripts matter: ~/.bashrc
is run for all non-login shells (that is, ones spawned from e.g. gnome-terminal
) but ~/.profile
is only run for login shells (that is, ones where you have to authenticate, such as SSH connections). So, at the bottom of ~/.profile
, we just start another gpg-agent
who doesn’t know about X:
eval $(gpg-agent --enable-ssh-support --daemon)
After restarting your SSH session and triggering a key operation, like signing a document, pinentry-curses
should ask for your passphrase at the SSH shell and not leave dialogs stranded in the X session.
Finally, that second agent shouldn’t be left hanging around after we’ve finished, or there’ll be hundreds of them soon. Fortunately, the PID is recorded in the environment variable GPG_AGENT_INFO
, but parsing that is a bit awkward when it’s also recorded alone in SSH_AGENT_PID
. So in ~/.bash_logout
, we just
kill $SSH_AGENT_PID
(Most of the pointers for this setup came from http://wiki.kumina.nl/index.php/Managing_ssh_keys_with_gpg-agent and http://stefaanlippens.net/bashrc_and_others)
A great write-up! Just one question: have you tried playing around with the “keychain” package? 🙂
I second Peter’s keychain suggestion.
http://www.gentoo.org/doc/en/keychain-guide.xml
I use it everywhere to manage my ssh and gpg agents. You can usually get by with as little as
eval $(keychain –eval –quick –quiet)
in your bashrc.
I’ve never found a need for either ssh-agent or gpg-agent on a remote system; I only ever need them locally. I don’t allow remote access to any system with my GPG key on it, and I use SSH agent forwarding to trusted machines on the rare occasions I need it.
On my local system, I let the X session scripts start gpg-agent, and I use libpam-ssh for ssh-agent.
Very interesting! I am also looking for the perfect gpg-agent setup, though I would like to satisfy another constraint that is, I think currently unavailable: to have the agent ask for confirmation each time a software want to use a key, telling me what process it is.