Motivation
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.
Tutorial
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~~~~0.0.1.0
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Then, download the latest version here:
https://github.com/PowerShell/Win32-OpenSSH/releases
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: https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH-Using-MSI):
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 github.com/jstarks/npiperelay@latest
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
:
[Unit]
Description=Relay ssh-agent from Windows to WSL using npiperelay
After=network.target
[Service]
ExecStart=socat UNIX-LISTEN:/tmp/ssh-agent-wsl,umask=007,fork EXEC:"npiperelay.exe -ep -s //./pipe/openssh-ssh-agent",nofork
[Install]
WantedBy=default.target
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!
Troubleshooting
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 (https://github.com/microsoft/WSL/issues/8843#issuecomment-1337127239) 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
Be First to Comment