Skip to content

Instantly share code, notes, and snippets.

Last active March 14, 2023 02:09
What would you like to do?
KeeAgent (for KeePass) on Bash on Windows / WSL (2)

Update (March 2023)

Side note: The latest edge build of KeeAgent plugin offers an option for creating a WSL compatible socket. This would be very handy. I already tried to use that socket, but the socket file is currently empty and ssh inside WSL 2 is unable to use it. This appears to be a very new, unreleased and unstable feature. I will follow the development of it and when it finally works (well, for me) I will update this HOWTO. But until then, please use the proven wsl-ssh-agent/npiperelay.exe approach below.

Thanks to the instructions for WSL 2 of the wsl-ssh-agent project, KeeAgent works great in WSL 2 now: The approach uses minimal and well maintained tools.


  • (03.03.2023) Change: Place the npiperelay.exe not onto the devfs filesystem but rather Windows filesystem (thanks @NOBUTOKA) which fixes strange delays when using the SSH keys.

Installation/setup (proven/best approach (wsl-ssh-agent+npiperelay.exe))

  1. Install the KeeAgent plugin for KeePass (2.x).
  2. The OpenSSH Authentication Agent Windows service must be stopped. For being sure that it stays stopped, even after rebooting, disable the service (when it is stopped).
  3. Open the KeeAgent options via KeePass Menu → Tools → Options → KeeAgent Tab. Enable the option Enable agent for Windows OpenSSH (experimental) A possible error message Windows OpenSSH agent is already running. KeeAgent cannot listen for Windows OpenSSH requests. can be ignored, everything will still work fine. (You may still find the Workarounds / troubleshooting section at the end of this HOWTO interesting). No socket files need to be created, the options can be left disabled.
  4. Necessary step (thanks @jacobblock): socat must also be installed:
sudo apt install socat
  1. Place the npiperelay.exe under the Windows filesystem (not onto the WSL system (devfs) filesystem! (thanks @NOBUTOKA)).

Place the npiperelay.exe under /usr/local/bin/npiperelay.exe inside your WSL 2 installation. It must be on the devfs filesystem, see Note on this change: Although the deprecated approach (of putting npiperelay.exe onto the devfs filesystem) still worked, it introduced strange delays. An user here noticed that placing npiperelay.exe onto the Windows filesystem (one can still symlink it into /usr/local/bin/ if one likes, not only didn't prevent it from running, but also fixed the delay. And indeed, the npiperelay repository itself states the opposite: The npiperelay.exe should be placed onto the windows filesystem, not onto devfs filesystem (interestingly, it would not have even run at that time as WSL hadn't supported running exe files in devfs, but apparently it also would introduce these delays).

Download instructions (thanks @musm; thanks @dmwyatt):

One suitable directory on the Windows filesystem can be C:\Users\<username>\wsl-keeagent\npiperelay.exe (%USERPROFILE%\wsl-keeagent\npiperelay.exe). You can easily get the compatible path in WSL by using this handy command: wslpath "$(wslvar USERPROFILE)".

# just to be sure the path is right
echo $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent)

# create dedicated directory on Windows filesystem
mkdir -p $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/)

# Download release ZIP into /tmp
# Release v1.5.2
wget -P /tmp

# Extract directly to the prepared Windows directory
sudo 7z e -y /tmp/ -o$(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/)

# Make the file executable
sudo chmod +x $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/npiperelay.exe)

# (optional) Clean up downloaded ZIP file
rm /tmp/

# Symlink `npiperelay.exe` back into `/usr/local/bin/npiperelay.exe`
sudo ln -s $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/npiperelay.exe) /usr/local/bin/npiperelay.exe

What if I followed this guide before this change (pre 3rd March 2023) and I already have npiperelay.exe at /usr/local/bin/npiperelay.exe? No problem, you can just move it out onto the Windows filesystem and even symlink it from there back to /usr/local/bin/npiperelay.exe, as this doesn't reintroduce the delay issue! See the instructions here

  1. Create a new script file ~/bin/wsl-ssh-agent-forwarder (thanks @r2evans) with the following contents:
# Usage: wsl-ssh-agent-forward [ -k | -r ]
# Options:
#    -k    Kill the current process (if exists) and do not restart it.
#    -r    Kill the current process (if exists) and restart it.
# Default operation is to start a process only if it does not exist.

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

sshpid=$(ss -ap | grep "$SSH_AUTH_SOCK")
if [ "$1" = "-k" ] || [ "$1" = "-r" ]; then
    if [ -n "${sshpid}" ]; then
        kill "${sshpid}"
        echo "'socat' not found or PID not found"
    if [ "$1" = "-k" ]; then
    unset sshpid

if [ -z "${sshpid}" ]; then
    rm -f $SSH_AUTH_SOCK
    ( setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"/usr/local/bin/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork & ) >/dev/null 2>&1

Ensure the script (text) file uses proper UNIX (LF) line endings - especially when you create/edit that file from a Windows editor. You can ensure proper UNIX line endings by using the handy dos2unix tool: (e.g. install it using apt-install -y dos2unix) dos2unix ~/bin/wsl-ssh-agent-forwarder. A telling symptom for incorrect line endings are errors like

command not found: ^M
command not found: ^M
parse error near `fi'

The bash script parser encountered characters that are used as line endings on non-UNIX systems, trying to interpret them and failing in the process. (thanks @jetzerb)

  1. Make the script executable: chmod +x ~/bin/wsl-ssh-agent-forwarder
  2. Add the following line to your .bashrc (~/.bashrc) to execute the script above:
# KeeAgent
. ~/bin/wsl-ssh-agent-forwarder

It is important that the script is sourced (. is shorthand for source), not just executed inside .basrc, as otherwise the exported environment variables would be used for the child process. The VSCode terminal is a case for this.

  1. Important: Ensure the socket file exists (even just as an empty placeholder file)!
mkdir -p $HOME/.ssh
touch $HOME/.ssh/agent.sock
  1. (Tip) Reload .bashrc config in current bash session:
$ source ~/.bashrc
  1. You can check the key agent functionality by either connecting via SSH or listing the keys with ssh-add -l (thanks @jacobblock). KeePass should automatically show the authentication prompt and/or notify that SSH keys have been accessed. Note: The KeePass program must be running when KeeAgent should be used. Turning on KeePass autostart could be a good idea.

Workarounds / troubleshooting

ssh-add -l

ssh-add -l is helpful for debugging as it simply tries to connect to the SSH Agent to list the available keys, reporting potential issues.

ssh suddenly doesn't use KeeAgent anymore / "Windows OpenSSH agent is already running" error message / TortoiseGit/TortoiseSVN

Once in a while I encounter the issue where ssh suddenly doesn't use KeeAgent anymore. The "Windows OpenSSH agent is already running" error message when closing/confirming the KeeAgent options dialog (KeePass Menu → Tools → Options → KeeAgent Tab) also appears then. This could be caused by a deeper, underlying issue: I noticed that this happens when updating TortoiseGit or TortoiseSVN (I have both installed). These tools also install their own version of PuTTY/Pageant - this may cause issues with KeeAgent which also tries to run its own SSH agent. Uninstalling TortoiseGit and TortoiseSVN appears to alleviate the issue. Of course, one still wants to use TortoiseGit and TortoiseSVN. An uninstall isn't necessary. It should be sufficient to just disable the PuTTY Pageant that ships with TortoiseGit and TortoiseSVN, so they don't interfere with KeeAgent (and they aren't used anyway).


The ~/bin/wsl-ssh-agent-forwarder script can also be manually invoked with a -r or -k paramter. -r makes it restart the SSH agent forwarding process, while -k kills it without restarting it (see the script comments). When the SSH client has issues using the forwarded SSH agent, using wsl-ssh-agent-forwarder with -r and -k (and restarting/reloading the shell) can fix those issues without the need for rebooting the whole system.


Some issues (probably some stuck process or socket or pipe) can be fixed by simply rebooting the sytem.


What if I followed this guide before this change (pre 3rd March 2023) and I already have npiperelay.exe at /usr/local/bin/npiperelay.exe? No problem, you can just move it out onto the Windows filesystem and even symlink it from there back to /usr/local/bin/npiperelay.exe, as this doesn't reintroduce the delay issue!

# just to be sure the path is right
echo $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent)

# create dedicated directory on Windows filesystem
mkdir -p $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/)

# Move `npiperelay.exe` from `devfs` filesystem to Windows filesystem
sudo mv /usr/local/bin/npiperelay.exe $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/)

# (optional) Change file ownership back from `root` to the normal user
sudo chown $USER npiperelay.exe

# Symlink `npiperelay.exe` back into `/usr/local/bin/npiperelay.exe`
sudo ln -s $(wslpath "$(wslvar USERPROFILE)"/wsl-keeagent/npiperelay.exe) /usr/local/bin/npiperelay.exe

Thanks to the symlink, nothing else (like paths) needs to be changed. You are done here, the fix is applied and the delays should be fixed now. No need to reload or restart either, as the binary is invoked each time, hence the next time the SSH agent is used, the binary at new location is used instead, which should fix the delay.

Note: Comments below may relate to the outdated Howto for WSL 1 and!

Copy link

dmwyatt commented Apr 8, 2021

Note that as of right now the latest version of wsl-ssh-agent.7z is 1.5.0. Make the appropriate changes to the wget command...

Copy link

strarsis commented Apr 9, 2021

@dmwyatt: I updated the version.

Edit: wsl-ssh-agent v1.5.1 was accidentally named wsl-gpg-agent (see rupor-github/wsl-ssh-agent#23).
This was fixed with v1.5.2 which is also used in this guide now. The release file format changed from tar to zip by the way.

Copy link

Thank you for making this!

I turned this into an ansible playbook so it's easy for me to use on my various boxes. Thought I'd share my gist in case it's useful to others:

Copy link

@eddieparker: That's very nice, thank you.

Copy link

Worked like a charm, I'm able to serve my SSH keys stored on KeePass to both Ubuntu Wsl2 and Windows OpenSSH at the same time. Thanks.

Copy link

Paullik74 commented Dec 21, 2021

thank you for this, working like a charm for me with only one issue, which is not issue of this i guess, but i would like to try ask if anyone have some idea..

im using PHPStorm for developing, with source code in WSL2.. problem is, im not able to do git pull or git fetch in PHPStorm directly, but with Terminal there is no issue..

Fetch Failed
			git@***: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
			Could not read from remote repository.
			Please make sure you have the correct access rights
			and the repository exists.

phpstorm git settings:

im able to do only commit in phpstorm gui, but then i need to do manual git push in open Terminal

once i installed GIT directly in windows and set it to use OpenSSH, then set phpstorm using windows git executable instead of wsl2 git, it started to work, taking SSH keys from KeeAgent without issues, but that is not solution what i like (because i need to keep configuring two instances of git)

any ideas anyone please?

Copy link

Copy link

@strarsis not exactly i would say, but maybe also related.. but this one is more related

Copy link

strarsis commented Jan 4, 2022

@Paullik74: Does the workaround with the SSH client config fixes your issue (last comment in that issue)?

Copy link

Paullik74 commented Jan 4, 2022

@strarsis well, im not able to do this, because i dont have key files in ~/.ssh, because i have them only in KeePass

~/.ssh$ ls -la
total 16
drwx------  2 filgap01 filgap01 4096 Jan  4 12:50 .
drwxr-xr-x 12 filgap01 filgap01 4096 Jan  4 12:50 ..
srwxr-xr-x  1 filgap01 filgap01    0 Jan  3 13:59 agent.sock
-rw-------  1 filgap01 filgap01  168 Jan  4 12:50 config
-rw-r--r--  1 filgap01 filgap01 1768 Nov 15 11:17 known_hosts
$ ssh-add -l
4096 SHA256:xxxxxxxxxxx (RSA) <---- key from KeePass

Copy link

strarsis commented Jan 5, 2022

@Paullik74: Can you invoke shell commands in the phpstorm context, is SSH_AUTH_SOCK set?
I had a similar issue with VSCode. The VSCode own terminals/shells hadn't have the SSH_AUTH_SOCK environment variable set,
hence the SSH agent wasn't used inside.

Can you set environment variables specifically for the context in which phpstorm runs?
How are you launching phpstorm? Inside WSL 2? As a native windows process?

Copy link

vietaalto commented Feb 8, 2022

why I have such error when sourcing ~/bin/wsl-ssh-agent-forwarder

/home/myusername/bin/wsl-ssh-agent-forwarder:7: command not found: ^M
/home/myusername/bin/wsl-ssh-agent-forwarder:9: command not found: ^M
/home/myusername/bin/wsl-ssh-agent-forwarder:28: parse error near `fi'

Copy link

jetzerb commented Feb 8, 2022

@vietaalto : looks like the file has DOS line endings (CR+LF) rather than UNIX line endings (LF).
You can change the endings via dos2unix wsl-ssh-agent-forwarder.
Then try again.

Copy link

Thanks so much for putting everything together!

The referenced link tells:

Put npiperelay.exe somewhere on devfs for interop to work its magic (I have winhome ⇒ /mnt/c/Users/rupor in my $HOME directory for that)

but this GIST uses /usr/local/bin/npiperelay.exe, which normally is not on C:, but in wslFS. When I read the HOWTO here, I did not understand from the GIST that it must be on C: (I thought it must not be on C: but must on the virtualFS. which is wrong).

Maybe a clearer note could be added or put the npiperelay.exe to %HOME%, C:\Windows\System32 or so (I found not way to automatically determine the %HOME% folder path in WSL - but please note on Windows it is common policy not to allow execution where users can write, so %HOME% might not work).

Copy link

I have Microsoft Windows [Version 10.0.19044.1826] but agent forwarding does not work:

sdettmer@AAD-CND123456:~ (master u+1) $ ssh-add -l
2048 SHA256:Kxxxxxxx 2020-03-12 (RSA)
sdettmer@AAD-CND123456:~ (master u+1) $ ssh tux6 -vv
debug2: callback start
debug2: x11_get_proto: /usr/bin/xauth  list 2>/dev/null
debug1: Requesting X11 forwarding with authentication spoofing.
debug2: channel 0: request x11-req confirm 1
debug1: Requesting authentication agent forwarding.
debug2: channel 0: request confirm 0
debug2: fd 3 setting TCP_NODELAY
debug2: client_session2_setup: id 0
debug2: channel 0: request pty-req confirm 1
debug1: Sending environment.
sdettmer@tux6:~ (master *$ u=) $ ssh-add -l
debug1: client_input_channel_open: ctype rchan 4 win 65536 max 16384
debug2: fd 8 setting O_NONBLOCK
debug1: channel 1: new [authentication agent connection]
debug1: confirm
debug2: channel 1: read<=0 rfd 8 len 0
debug2: channel 1: read failed
debug2: channel 1: close_read
debug2: channel 1: input open -> drain
debug2: channel 1: ibuf empty
debug2: channel 1: send eof
debug2: channel 1: input drain -> closed
debug2: channel 1: rcvd eof
debug2: channel 1: output open -> drain
debug2: channel 1: obuf empty
debug2: channel 1: close_write
debug2: channel 1: output drain -> closed
debug2: channel 1: rcvd close
debug2: channel 1: send close
debug2: channel 1: is dead
debug2: channel 1: garbage collecting
debug1: channel 1: free: authentication agent connection, nchannels 2
error fetching identities: communication with agent failed
sdettmer@tux6:~ (master *$ u=) $

I think WSL #3183 is not present in my version, because it already has been fixed (right?).

Any hints?

Copy link

Bond246 commented Sep 6, 2022

Hello everyone,

since some days on my business notebook the agent is not working anymore.
I tried to reinstall everything and checked everything i thought it could be:

  • reinstalled npiperelay
  • rewrite the wsl-ssh-agent-forwarder
  • reconfigured KeeAgent and so on

nothing works

agent.sock is 0 bytes and ssh-add -l just outputs
error fetching identities: communication with agent failed

Same configuration on my private Win11 machine is working fine.

Does anyone have an idea what to check?
Problem is that login via SSH needs much much moments until password-prompt appears which is really annoying.


Copy link

Bond246 commented Sep 7, 2022

i don't get a error message like "openssh already running" when opening KeeAgent in Keepass-Options.

But is there any option to check oder any log to review to find a hint for what is going wrong?

Copy link

@Paullik74 I used this setup with Pycharm. To make it work, I had to create a bash script to wrap git:

export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
/usr/bin/git "$@"

In pycharm (or PHPStorm), go to Settings - Version Control - Git and choose the path to this bash script as the path to Git executable.

Copy link

strarsis commented Oct 4, 2022

@Bond246; @sdettmer: A new version of KeeAgent recently released:
Updating may help with the issue (the CHANGELOG comment Fix crash when process disappears before connecting to Windows OpenSSH agent (thanks Samuel D. Leslie). may relate to your issues).

Copy link

I am having some delay issues using WSL2, ssh-add -l and other ssh commands using the ssh agent are delayed by 5 seconds, but on cmd they are executed instantly. Anyone else having these issues?

Copy link

@antoniozh: Sometimes I have this issue sometimes. I am not sure what is causing it. 🤔

Copy link

I suspect that npiperelay as the bridge between the Windows OpenSSH agent and WSL is causing the delay, since on cmd it works just fine.

Copy link

tueur-a-gage commented Feb 1, 2023

Same issue on my side (long delay for response).

Copy link

I found the solution for this delay issue.
Do NOT place npiperelay.exe in /usr/local/bin/ or other directory inside WSL.
Instead, place it under directory inside the Windows file system, such as /mnt/c.
If you want, create simlink to npiperelay.exe in /usr/local/bin.
The delay will be disappeared.

Refer: jstarks/npiperelay#26

Copy link

strarsis commented Feb 21, 2023

@NOBUTOKA: That's interesting! Because basically the opposite is known to work/recommended: That npiperelay.exe should be placed inside /usr/local/bin/ or at least on the devfs filesystem in WSL. So these changes improved the performance for you? And it works? 🤔

Copy link

@strarsis Yes, it works for me.
I had experienced 5 seconds delay in every single ssh access while npiperelay is placed under /usr/local/bin directly,
and after it placed under /mnt/c, there is no delay.

Copy link

@strarsis, same things for me, npiperelay.exe was on /usr/local/bin as indicated, and since around 1 month (windows update ??) it was very slow. By putting it on /mnt/c/...somewhere and do a symbolic link as indicated by @NOBUTOKA no it works fine.
Many thanks for the trick !

Copy link

GlucNAc commented Feb 27, 2023

@strarsis Thanks for the tip it also help me to stop the freezing!

Otherwise, I've made a script to install the connection between my Debian distro and Windows SSH agent :

Another interesting point is that you can use Docker images as WSL distro. So I've made a Debian slim docker image with that connection to windows SSH agent, and then I've install it as a WSL2 distro using this script :

In that way, no need to make an Ansible script or a custom shell script to install my set up :)

Copy link

strarsis commented Mar 3, 2023

@NOBUTOKA, @tueur-a-gage, @GlucNAc, @antoniozh, @fracaron, @Bond246, @sdettmer:
Important update!
There were contradicting information on where to put the npiperelay.exe, either it has to be on the devfs filesystem or on the Windows filesystem.
It turns out that a) it can be now put onto the Windows filesystem without preventing its proper functionality and b) it should be actually put onto the Windows filesystem as this prevents the strange delay issues some users (including me) experienced (thanks @NOBUTOKA).

The guide as updated to reflect this (step 5), including extra instructions for those who already put the npiperelay.exe into the devfs filesystem, prior to this update:
It is very simple to change and indeed, the delays went away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment