SSH with gpg-agent on systemd



This content originally appeared on DEV Community and was authored by Erik Huelsmann

There’s a lot of information floating around on the web explaining how to replace ssh-agent with gpg-agent. This is important if you – like me – want to use a yubikey or smart card device to store the private key of your SSH key pair.

Unfortunately, none of the advice worked for me with the following system setup:

  • systemd v249
  • GNOME desktop 42.9
  • Ubuntu 22.04

Although the above is quite specific, I expect the information below to much more generally applicable.

Prerequisite for Yubikeys and smart cards

GPG needs pcscd and scdaemon to be able to access private keys stored on a yubikey or smart card:

$ sudo apt install pcscd scdaemon
$ systemctl enable --now pcscd
$ systemctl enable --now scdaemon

After running these commands, gpg --card-status should provide you with information about your smart card.

Configuring GPG with ssh-agent support

To enable ssh-agent support in gpg-agent, add the following to your gpg-agent.conf:

# ~/.gnupg/gpg-agent.conf
enable-ssh-support

Enabling gpg-agent (per user)

gpg-agent is a per-user service, which systemd facilitates with the --user flag on the systemctl command:

$ systemctl enable --user --now gpg-agent.socket
$ systemctl enable --user --now gpg-agent-ssh.socket

If you forget to add the .socket extension, systemctl will throw an error about a missing [Install] section in the service definition. Please note that the sockets are to be enabled; the service itself is to be left untouched.

Verifying status of the GPG agent can be done using:

$ systemctl status --user gpg-agent.socket
$ systemctl status --user gpg-agent-ssh.socket

Although the service is now running, the environment shows an incorrect value for SSH_AUTH_SOCK ().

Fixing SSH_AUTH_SOCK

There are several configurations blocking successful use of gpg-agent for SSH, causing the value of SSH_AUTH_SOCK to be incorrect.

Disable ssh-agent user service

If it is enabled, this service needs to be disabled, as it is conflicting:

$ systemctl disable --user --now ssh-agent

Disable Xsession.options ssh-agent

The Xsession script tries to start an ssh-agent. This can be disabled by modifying /etc/X11/Xsession.options and /etc/X11/Xsession.options.d/*.conf, making sure the last file loaded contains:

no-use-ssh-agent

This is best achieved by creating a file named /etc/X11/Xsession.options.d/zz-no-ssh-agent.conf with that content.

Disable GNOME Keyring (gnome-keyring-ssh.desktop)

GNOME Keyring tries to start an SSH agent if none is running. The way to disable this is by executing the following commands – which are different from those published all around:

$ cp /etc/xdg/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/gnome-keyring-ssh.desktop
$ echo "X-GNOME-Autostart-enabled=false" >> ~/.config/autostart/gnome-keyring-ssh.desktop
$ echo "Hidden=true" >> ~/.config/autostart/gnome-keyring-ssh.desktop

The “Hidden=true” addition is advertized all around the web, but didn’t work for me.

Setting SSH_AUTH_SOCK

Using systemd to manage gpg-agent has one drawback: systemd doesn’t set environment variables in the user shell session. This can be solved by adding this snippet to the user’s bashrc:

# to be appended to ~/.bashrc
if [[ -z "$SSH_AUTH_SOCK" ]]
then
  if [[ -e "/run/user/$(id -u)/gnupg/S.gpg-agent.ssh" ]]
  then
    export SSH_AUTH_SOCK="/run/user/$(id -u)/gnupg/S.gpg-agent.ssh"
  fi
fi

Conclusion

Yubikey and smart card support with private keys on the key or card does not come out of the box, even in this day and age, but with a bit of configuration, setting up private keys on a smart card and making it work under GNOME, is doable.


This content originally appeared on DEV Community and was authored by Erik Huelsmann