Mendhak / Code

How to use KeepassXC to serve SSH keys to WSL2 and Ubuntu

I have previously shown how to serve keys to WSL1, here I’ll be going over the method to do it for WSL2.

KeepassXC can be used to serve SSH keys to WSL2, which is useful when remoting on to servers, or using Git over SSH. Some benefits of putting your SSH key into your KeepassXC are that you can have a strong password on the private key but don’t need to type it out each time, and that you don’t need to save your keys on disk - you can let KeePassXC manage the storage, unlocking and serving of the keys for you.

You can also skip the steps and go straight to the setup script

Set up KeePassXC

Open up KeePassXC’s settings, and choose to Enable SSH Agent and also Use OpenSSH for Windows instead of Pageant.
The second option requires the OpenSSH service in Windows to already be running, you will get an error message if it isn’t.

keepassxc settings

Store an SSH key

Create a new entry in your database, give it some name, and in the password field, put the passphrase for your SSH key.

In the advanced section, attach your public and private key, then hit OK, then save the entry. You need to save so that the SSH Agent can read your key in the next step.

Now reopen the entry, then go to the SSH Agent section, under Private key, pick the file you attached earlier. The rest of the section should get filled out with details about your key. Once again hit OK and save; KeePassXC is now serving those keys to the Windows SSH agent.

KeePassXC settings

Get Npiperelay

npiperelay allows named pipes to communicate between Linux in WSL and Windows. Although it’s a Windows based tool, it’s still possible to run it from within WSL2, which makes for a convenient setup.

In your WSL2, download and extract the npiperelay binary.

cd ~
unzip -d npiperelay

This puts the npiperelay.exe at /home/username/npiperelay.

You can also download npiperelay to the Windows side, and substitute the corresponding path below with slash notations, such as /c/Temp/npiperelay.exe

Install socat

In your WSL2, install socat, to allow communication with npiperelay.

sudo apt install socat

Tell WSL to use it

You will need to tell WSL2 to talk to npiperelay via socat, so that it can talk to Windows SSH Agent, so that it can fetch your keys from KeePassXC.

In your ~/.bashrc, add the following lines. This code checks to see if the agent socket is up,

export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock

ss -a | grep -q $SSH_AUTH_SOCK
if [ $? -ne 0 ]; then
    rm -f $SSH_AUTH_SOCK
    (setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"$HOME/npiperelay/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork &) >/dev/null 2>&1
If you’ve put npiperelay.exe in another location, replace the $HOME/npiperelay/npiperelay.exe above.

Exit and reopen your shell, and this should call out to npiperelay. There is no visual indication to know it’s working, you can only find out by testing it.

Test it

Assuming you’ve already added your public key to Github, do a quick test.

$ ssh -T [email protected]
Hi mendhak! You've successfully authenticated, but GitHub does not provide shell access.

All together in one script

Save this to a bash script and execute it. It should do all of the above steps including writing to ~/.bashrc.

cd ~

echo "Get npiperelay"
unzip -o -d npiperelay

echo "Install socat"
sudo apt -y install socat

echo "Add to .bashrc"
cat << 'EOF' >> ~/.bashrc
export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock

ss -a | grep -q $SSH_AUTH_SOCK
if [ $? -ne 0 ]; then
    rm -f $SSH_AUTH_SOCK
    (setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"$HOME/npiperelay/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork &) >/dev/null 2>&1

echo "Reload ~/.bashrc"
exec bash

echo "Done"

Troubleshooting Notes

Make sure the versions match

On Windows 11, you may also need to ensure that the OpenSSH versions match or are close enough. First, check the Ubuntu SSH version.

$ ssh -v localhost
OpenSSH_8.9p1 Ubuntu-3ubuntu0.1, OpenSSL 3.0.2 15 Mar 2022

On Windows 11 I’ve found the version of OpenSSH is a bit older so I’ve had to install a later, matching version using winget. In Powershell:

> winget install Microsoft.OpenSSH.Beta --version

Once these versions were close enough, the SSH Agent started working.