March 4, 2024

gpg-agent as ssh-agent

Any reasonably recent systemd based desktop distro will have a gpg-agent that is launched in supervised mode on login. Supervised means that it will be killed on logout. This implies that passphrases will have to entered again after logout.

The setup below works on Chrom{e,ium}OS too.

pinentry

The terminal where you set export GPG_TTY=$(tty); echo updatestartuptty | gpg-connect-agent is where pinentry will ask for the passphrase.

  • If you happen to be running some curses thing when pinentry decides to use the pts, not only will pinentry not be able to read your passphrase, it will leave your pts in a state where you can’t even call tput reset to fix it.
  • If something caused pinentry to popup somewhere and you were on some other pts and thought, “Oh, I’ve probably not set GPG_TTY”, and run the incantation, not only will pinentry not be able to read your passphrase, it will leave your pts in a state where you can’t even call tput reset to fix it.

Just install pinentry-gtk2 or pinentry-gnome3 as appropriate. Attempting to use emacs or the shell for pinentry is an exercise in yak-shaving.

gpg-agent

Defaults to caching passphrases for 30 mins. It does not enable ssh-agent support by default. Add the following to ~/.gnupg/gpg-agent.conf,

enable-ssh-support
disable-scdaemon
grab
max-cache-ttl 86400
default-cache-ttl 43200
max-cache-ttl-ssh 864000
default-cache-ttl-ssh 864000

grab is the bit that messes up the pts if used incorrectly. It is a trade off between security and UX.

gpg-connect-agent reloadagent /bye should reload the agent after editing its config file.

Your shell setup should call the below somewhere

[[ -v SSH_AUTH_SOCK ]] || export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)

kitty ssh

Since kitty takes a radical approach to terminals, it requires its terminfo config to be present on remote hosts. If you can, run apt install kitty-terminfo on long lived hosts. If you cannot, there is an ssh kitten that works for basic usage. You might still need export TERM=xterm for some programs with the kitten.

alias ssh='kitten ssh'

Now, if you have a keybinding like below to open tabs to remote boxen,

map kitty_mod+g>r	launch --type=tab --title=rpi5 kitten ssh -t rpi5.local tmux -u new-session -ADs rpi5

kitty will not be able to find the ssh-agent as SSH_AUTH_SOCK is set by the shell and kitty will not have the variable when it tries to launch a process. There are many ways to set environment variable per user session but the simplest is to create a file ~/.config/environment.d/ssh-agent.conf with contents

SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh

The rhs needs to be static.

In 1995, when I was getting started on Linux, I used to laugh at Windows asking me to restart my PC to set an environment variable. After all these years of pam, policykit, DBus, and systemd, you could run dbus-update-activation-environment --systemd --all and then restart your machine to have everything working properly.

Agent Forwarding

On trusted boxen, you can enable agent forwarding with the following stanza in ~/.ssh/config.

Host *.alephnull.site *.local
     RemoteForward /run/user/1000/gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent.extra

Powered by Hugo & Kiss.