Skip to content

Forward WSL ssh-agent to Windows ssh-agent


ssh-agent can store your SSH key passphrase so you don’t have to type your ssh key password to unlock it every time. However, without being able to store the encrypted passphrase in the linux keychain, you still need to re-enter it on every reboot. By forwarding ssh-agent in WSL to use the Windows OpenSSH ssh-agent, you can access all your keys in one place and integrate with the Windows keychain so your passwords are stored between reboots.

When you add keys to the ssh-agent (e.g.ssh-add C:\Users\myuser\.ssh\id_ed25519, it asks you for your ssh key password. The Windows GUI keychain function attaches this password to your Windows user password, so that when you log into your Windows account, the SSH keys in ssh-agent are automatically unlocked.

This is all fine and dandy until you start using WSL and want to SSH from your Linux environment. the Linux ssh-agent can’t use the GUI keychain functionality if there is no GUI, the Linux keychain CLI tool doesn’t store passwords between reboots, and Linux’s ssh command can’t communicate with the Windows ssh-agent.

Until now.


1. Install latest OpenSSH client

First, make sure you have the latest OpenSSH (>= 9.1.0) installed.

# (optional) Uninstall old OpenSSH version first in "Optional features" if it's already installed / enabled
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~

Then, download the latest version here:

For this tutorial, we won’t need to install the OpenSSH server, just the Client. Either click on the msi installer and select the option to install the Client but not the server, or you can do it like this (additional details here:

msiexec /i <path to openssh.msi> ADDLOCAL=Client

Ensure ssh-agent is running by making sure the named pipe exists. You can see if you find openssh-ssh-agent at this page in Chrome (Firefox didn’t work) file://./pipe//, or run the following command in PowerShell/CMD:

# Ensure named pipe for ssh-agent exists
dir \\.\pipe\openssh-ssh-agent
2. Install npiperelay

Now that OpenSSH is set up, we need to install Go (using winget) so that we can install npiperelay

winget install -e --id GoLang.Go.1.19
# npiperelay saves the day!
go install
2. Configure WSL Distro

Now that npiperelay is installed, we just need to set up our Linux environment in WSL to connect to the Windows ssh-agent when bash starts. A slick way to do this is to use a systemd user service:

Create this file $HOME/.config/systemd/user/relay-ssh-agent.service:

Description=Relay ssh-agent from Windows to WSL using npiperelay

ExecStart=socat UNIX-LISTEN:/tmp/ssh-agent-wsl,umask=007,fork EXEC:"npiperelay.exe -ep -s //./pipe/openssh-ssh-agent",nofork


Link npiperelay.exe to /usr/local/bin so that it’s in your path

# Link npiperelay.exe from windows place in Linux path
ln -s /usr/local/bin/npiperelay.exe /mnt/c/Users/myuser/go/bin/npiperelay.exe

Run systemctl --user start relay-ssh-agent.service to start the service! You can enable the service so that it runs whenever Linux starts.

Now start a new shell and run ssh-add -L to verify your Windows keys are accessible from your Linux console. You should now be able to ssh into any of your hosts from Linux without entering a password!


MZ Not found

If you are getting an error like:

/usr/local/bin/npiperelay.exe: 1: MZ@: not found
/usr/local/bin/npiperelay.exe: 2: Syntax error: Unterminated quoted string

You may be having an issue with WSL interop. Thanks to ( for this fix:

# Create WSLInterop config
echo ":WSLInterop:M::MZ::/init:PF" | sudo tee -a /usr/lib/binfmt.d/WSLInterop.conf

# Restart systemd-binfmt
sudo systemctl restart systemd-binfmt
Published inDevelopmentTutorials

Be First to Comment

Leave a Reply