Forwarding GPG over SSH | Alt255 Blog

December 17, 2017

Forwarding GPG over SSH

Here’s a guide to forwarding GPG over SSH. This is helpful to not only assist with remote GPG operations, but will also work to forward SSH credentials which were loaded via gpg-agent.


With modern versions of GPG (eg GnuPG 2.1), the gpg-agent will automatically create sockets in $HOME/.gnupg:

$ ls -l $HOME/.gnupg/S.gpg-agent*
srwx------  1 jburke  staff  0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent=
srwx------  1 jburke  staff  0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.browser=
srwx------  1 jburke  staff  0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.extra=
srwx------  1 jburke  staff  0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.ssh=

Access to these sockets provides access to the gpg-agent. If you’ve unlocked your PGP key or SSH key, they will be accessible via the sockets.

The S.gpg-agent.extra socket is a bit special in that it provides access to the PGP key, but restricts which commands can be used. See the documentation for --extra-socket for more information.

To enable the extra-socket, add something like the following to your .gnupg/gpg.conf:

extra-socket /Users/jburke/.gnupg/S.gpg-agent.extra

Setup SSH config

Now we’ll configure SSH to forward the (restricted) PGP key socket and SSH agent forwarding:

Add to .ssh/config:

        RemoteForward /home/jburke/.gnupg/S.gpg-agent /Users/jburke/.gnupg/S.gpg-agent.extra
        RemoteForward /home/jburke/.gnupg/S.gpg-agent.ssh /Users/jburke/.gnupg/S.gpg-agent.ssh

Note that the format of RemoteForward is RemoteForward <remote target> <local target>.

On the remote host, test that it’s working by gpg2 --card-status.

If only forwarding the “extra” socket, you’ll receive these errors:

$ gpg2 --card-status
gpg: error getting version from 'scdaemon': Forbidden
gpg: selecting openpgp failed: Forbidden
gpg: OpenPGP card not available: Forbidden

Those errors about “Forbidden” are expected since we’re only forwarding the S.gpg-agent.extra socket which has reduced privileges.


If the desintation host already has gpg-agent running, it may have setup its own sockets. The quickest way to reset the world is:

On remote host, make sure to killall gpg-agent. Also: rm ~/.gnupg/S.*.

Then ssh to remote. Verify with gpg2 --card-status.

Needing to reset the remote environment by killing the gpg-agent and manually removing the sockets is not a satisfying workflow. Will need to figure out a method to automate.


Excellent writeup from GnuPG here. Discusses alternatives if using an older version of GPG.