
Sequel and amplification of Sébastien Picardeau’s step-by-step study (Sep. 2025). Same goal, fewer steps, and one new property: SSH multi-hop with the same physical key.
You ssh into several machines a day. On those, you produce digital signatures, decrypt files, or ssh further out. The textbook answer is to copy your private keys to each of those machines — and to bet that the next mass-surveillance push or cyber-attack will not take your secrets as the prize. That answer aged badly.
The correct answer has existed for years (forwarding gpg-agent and ssh-agent over SSH), but the setup is fiddly enough that almost nobody runs it. We packaged that correct answer as a tool. It is called sshwgpg, it fits in 140 lines of Bash, and it ships in our Debian package repository .
On a local machine that has access to your OpenPGP keys, you type:
sshwgpg user@remote.example
And you land in a rather welcoming remote session:
gpg --sign, gpg --decrypt or git commit -S work on the remote using your signing or decryption keys locally;ssh user@other.example or sshwgpg user@other.ex work on the remote using your OpenPGP authentication keys locally.Two sockets, one command, one OpenPGP certificate. The bytes of your private keys never leave your computer — or better still, if you use a YubiKey or NitroKey: the chip deep inside its silicon.
Most “gpg agent forwarding” recipes you find online stop at the first hop. Forwarding the SSH_AUTH_SOCK=…gpg-agent.ssh socket that sshwgpg includes is what lets you hop further, more easily:
you$ sshwgpg mneme@serverA.org # ssh properly configured (cf. SSH_AUTH_SOCK) lets you authenticate with your OpenPGP key.
serverA$ sshwgpg mneme@serverB.org # ssh auth via your OpenPGP key, physically secured by your YubiKey/NitroKey.
serverB$ git commit --gpg-sign # commit signed by the same OpenPGP key, which has not left the YubiKey/NitroKey you carry.
serverB$ git push origin main # commit pushed via ssh authenticated by your OpenPGP key — still on you, still cosy.
Each hop reaches back, through the previous hops, to the same OpenPGP key on the original machine. Unplug the YubiKey/NitroKey: no machine can sign, decrypt or authenticate any more. Coupled with a YubiKey/NitroKey, sshwgpg delivers the digital equivalent of a handwritten signature at a distance — yet still of your hand.
While a physical security key is plugged in, any privileged process (root, or a compromise) can ask your YubiKey/NitroKey to sign, decrypt or authenticate something other than what you initiated. We can shrink the attack surface to a sliver with a few guardrails:
(1) is on by default. (2), (3) and (4) are choices you make for the level of security you want. (5) is the only one no software can give you.
The remote sshd needs one option set:
# /etc/ssh/sshd_config.d/80-StreamLocal.conf
StreamLocalBindUnlink yes
Without it, sshd refuses to overwrite an existing forwarded socket and sshwgpg’s second connection cannot rebind. That’s the entire server-side requirement to make sshwgpg work — and Sébastien’s 2025-09-07 study is the long version of why.
sshwgpg’s only runtime dependency is openssh-client. Source and Debian packaging live at https://codeberg.org/foopgp/sshwgpg . Currently shipped via our Debian packages repository :
sudo apt install sshwgpg
sshwgpg is the client-side tool. To use it productively against a fleet of servers you would otherwise have to configure each one: the sshd option above, an ~/.ssh/authorized_keys with the right SSH subkey, gpg-agent set up to honour the forwarded socket, SSH_AUTH_SOCK pointed at gpg-agent’s ssh socket in every login shell, etc.
The djibian-gpgconfig package does all of that for you:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) — every login shell naturally points at the forwarded socket) ;And on the user-provisioning side, the bashlibs-pgpid package turns a 40-hex-char OpenPGP fingerprint into a full Linux account:
What that looks like end-to-end:
# On the djibian.example server, as admin:
sudo bl-djibian adduser --from-certificate D995BB48C67FD9C1E8A03F7CDEC98791AADC429B
# From your machine, your YubiKey/NitroKey plugged in:
sshwgpg mneme@djibian.example
# You hold Mneme's security key and know her PIN: you are Mneme; from djibian.example you sign, decrypt or push as if at home
On a non-Djibian server the same wiring is a useradd and several shell lines or configurations — see previous study
.
The cloud model says: your secrets live on their servers, trust them. What sshwgpg (and the rest of the OpenPGP ID chain) makes possible is the opposite: servers cannot read your secrets without the key you hold in your hand. They can no longer manipulate your data behind your back; you take the control back, literally, through your physical security key: a YubiKey or NitroKey.
Everything in this chain is free software, auditable, and ships in our Djibian packages.
bl-djibian adduser) : https://codeberg.org/foopgp/bash-libsUsage : sshwgpg [OPTIONS] [SSH_OPTIONS] destination [SSH_OPTIONS] [command [argument …]]
Options :