KeePassXC, ssh-agent, and KDE
KeePassXC is a password manager. I make heavy use of its browser integration in Firefox. And I also store my private SSH keys (e.g. for git or deployment) in a .kdbx database.
KeePassXC has an SSH Agent integration. It communicates with the SSH Agent via a socket that is created by the SSH Agent on startup. One great feature of KeePassXC is the loading and unloading of SSH keys to and from the SSH Agent, either manually or upon unlocking and locking of a .kdbx database.
This setup worked well until I recently. After a system upgrade, KeePassXC could not anymore remove keys from the SSH Agent.
Understand the problem
KeePassXC connects to the socket advertised in the environment variable
SSH_AUTH_SOCK. When looking at that variable, I noticed that the socket
(/run/user/1000/gnupg/S.gpg-agent.ssh) was created by the GPG-Agent.
The gpg-agent service is a drop-in replacement for the ssh-agent service and it
does not support unloading SSH keys.
There we have it. KeePassXC was loading all of its keys to gpg-agent
which refused to forget them.
Remove keys from PGP-Agent
PGP-Agent stores private keys in the .gnupg/private-keys-v1.d/ directory.
These files are named keygrip.key. You can find the keygrip of the keys
you are using with GnuPG (for signing and encryption) with
paul@pycache:~$ gpg --list-secret-keys --with-keygrip
/home/paul/.gnupg/pubring.kbx
-----------------------------
sec rsa4096 2019-09-15 [SC] [expires: 2035-09-13]
WG0OVWA1M0GPQDAWNPMTW67MEKD3NZAPK72SZ
Keygrip = 5SUUGGFI8U8SWEPBSPZ3NY82JFTE0NYV1PV3N
uid [ultimate] Paul Müller <dev@pycache.de>
ssb rsa4096 2024-08-10 [S] [expires: 2034-08-08]
Keygrip = 8DGONGBBF7YH5K9NGNLVB1VQ7PWBHE637EDJC
Remove those keys that (are not listed here and) you want to use
with ssh-agent, managed by KeePassXC, from that private key directory.
Set up vanilla ssh-agent
To replace gpg-agent with the vanilla ssh-agent (which supports unloading
keys), first make sure that you have ssh-agent installed. On Debian,
ssh-agent is included in the openssh-client package. You can test this
by starting a new instance of ssh-agent:
paul@pycache:~$ eval `ssh-agent -s`
Agent pid 64141
Why the eval? Because ssh-agent prints a script to stdout that
sets all necessary environment variables when executed. If you ran
just ssh-agent -s, you would get the following output:
SSH_AUTH_SOCK=/tmp/ssh-LiIlmPqRAPpA/agent.64140; export SSH_AUTH_SOCK;
SSH_AGENT_PID=64141; export SSH_AGENT_PID;
echo Agent pid 64141;
Now set the SSH_AUTH_SOCK override option in the KeePassXC settings to the
environment variable that you have in your current shell:
paul@pycache:~$ print $SSH_AUTH_SOCK
/tmp/ssh-LiIlmPqRAPpA/agent.64140
Now you can use ssh-add -l in the same shell to list all private keys loaded.
Loading and unloading them in KeePassXC should now work here.
Setting up autostart of ssh-agent for KDE Plasma
This is a slim approach to what Lioh Möller from gnulinux.ch (archive.org) proposes. We don’t need to ask for passwords, since KeePassXC handles everything.
Simply create these files, log out and back in, and everything should work fine with the default settings in KeePassXc.
Start the agent via ~/.config/plasma-workspace/env/ssh-agent-startup.sh:
#!/bin/sh
[ -n "$SSH_AGENT_PID" ] || eval "$(ssh-agent -s)"
Stop the agent via ~/.config/plasma-workspace/shutdown/ssh-agent-shutdown.sh:
#!/bin/sh
[ -z "$SSH_AGENT_PID" ] || eval "$(ssh-agent -k)"
And make sure those files are executable (chmod +x path_to_script.sh).
