Motivation
It's annoying to enter your ssh key password to unlock it every time you reboot. In newer versions of Windows, you don't have to, as Windows now has a native version of OpenSSH.
When you add keys to the ssh-agent
(e.g.ssh-add C:\Users\me\.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
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 (NOT Firefox) file://./pipe//
, or run the following command in PowerShell/CMD:
# Ensure named pipe for ssh-agent exists. ( Can use browser to browse to ), or run
dir \\.\pipe\openssh-ssh-agent
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/[email protected]
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 can be executed from anywhere in Linux
# Link npiperelay.exe from windows place in Linux path
ln -s /usr/local/bin/npiperelay.exe /mnt/c/Users/joba/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!