Comprehensive Guide to ssh-agent on Windows and WSL

Wondrous Oxblood Cheetah
6 min readFeb 5, 2023

--

We have ssh natively on Windows now! So how do we setup our ssh environment to be consistent, predictable, safe and easy to use between Windows and WSL?

I want my ssh environment on my Windows workstation setup in a way, that on the first run of a ssh command, I only need to enter my ssh private key passphrase once, so it gets “saved” for the current session until i lock or reboot my workstation.
As a bonus on top, I would like the ssh environment in my WSL instance to use the same keys and config!

Basically just like the popular Keepass password manager behaves.

Unfortunately I was unable to find a guide, which explains how to accomplish this, so I wrote this article explaining my current method to achieve this functionality! (If you have a better/different way, or any questions, just leave a comment!)

Setting up OpenSSH

Activate the OpenSSH Client

The OpenSSH Client should in most cases already be active.
To check, just open the “Optional Features” page in Settings, where you should either find “OpenSSH Client”, or can add it via the “Add a feature” button.

Generate ssh keys

Please read for yourself what the best ssh-keygensettings are, but I like to use this recommendation:

ssh-keygen -t ed25519 -a 100

I would recommend using a passphrase for your private key, as this works as sort of a second factor, so bad actors won’t be able to access other hosts with just stealing your private key.

If you need compatibility with older systems, not supporting (OpenSSH Version ≤ 6.5 ) ED25519, use: ssh-keygen -t rsa -b 4096 -o -a 100
If you are using OpenSSH Version ≥ 7.8, you will need to omit the -o option.

Use best-practices regarding Key Algorithms allowed by your ssh client

Open your Windows OpenSSH Client Config.
You can use this PowerShell command (in an Administrator PowerShell, or use gsudo):

New-Item -ItemType File -Path $env:programdata\ssh\ssh_config | Out-Null; notepad $env:programdata\ssh\ssh_config

According to the Secure Secure Shell article, I compiled this config file.
Feel free to comment lines out, if you encounter compatibility issues:

# info by https://stribika.github.io/2015/01/04/secure-secure-shell.html

# If you see "unable to negotiate with ..." while connecting to a host, comment in the following lines and add the domain to the "Host" line seperated by spaces
#Host github.com
# KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
# MACs hmac-sha1-96

Host *
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
UseRoaming no

Save & Exit Notepad. Your SSH Client should use the new settings for all new connections.

Note: If you previously had entries in .ssh/known_hosts you will probably get messages of changed host keys when trying to connect to known hosts. This is due to the fact, that your ssh client now requests Host Fingerprints in other Algorithms and thus they don’t match the known ones.

Using the Windows ssh-agent in WSL

Did you know, you can directly call & run.exe files in your WSL terminal?
This makes this whole section extremely simple!

Just add these two lines to your ~/.bashrcor equivalent file and you’re done!

alias ssh-add='ssh-add.exe'
alias ssh='ssh-add.exe -l > /dev/null || ssh-add.exe && echo -e "\e[92mssh-key(s) are now available in your ssh-agent until you lock your windows machine! \n \e[0m" && ssh.exe'

If you also want git to use ssh.exe, just enter:

git config --global core.sshcommand "ssh.exe"

How to use ssh-agent

We now have 2 options, to use ssh-agent:

  • Automatic: Always load our ssh-key on start-up, without entering our passphrase ever again.
  • Manual: Only load our ssh-key into the ssh-agent, when running the ssh command. This way we will always need to enter our passphrase when first adding our ssh-key into ssh-agent for the first time in our session.

Activate ssh-agent daemon on log-on

Open the “Services” application, scroll down to “OpenSSH Authentication Agent”, right-click the entry and set “Startup Type” to “Automatic”.
Click “Apply” and then start the service via the “Start” button.

This ensures, that the ssh-agent and with it the ssh-addcommand (which we will use later) are available, as soon as you log in with your user.

Alternatetively you can also use these two PowerShell commands (in an Administrator PowerShell, or use gsudo):

Set-Service -Name 'ssh-agent' -StartupType Automatic
Start-Service ssh-agent

We can now manually add our ssh-key with ssh-add.
It will now stay loaded (even during reboot and Windows lock (WIN + L)) until we remove the key from ssh-agent with ssh-add -D.

If you want the manual version, keep going! If you want the automatic version, you are done!

Clearing ssh-agent on windows lock

Sadly, there is no built-in way in OpenSSH on Windows to do this automatically, so we will create an Automatic Task in “Task Scheduler”.

After opening “Task Scheduler” left-click and then right-click on “Task Scheduler Library” in the left pane, and select “Create Task” where will do the following:
- General: Enter an appropiate name like “ssh-add clear on windows lock”
- Triggers: “New…”, Begin the task: “On workstation lock”, “OK”
- Actions: “New…”, Program/script: “ssh-add”, Add arguments: “-D” (capital D is important here), “OK”
- Conditions: Remove the tick from the box next to “Start the task only if the computer is on AC power”
- Finally: Select “OK”

Our scheduled task should now be created and be visible in the “Task Scheduler Library” Folder!

Automatically add ssh-key to ssh-agent on first run of ssh

If we now lock our machine and unlock it again, we will notice, that our passphrase protected ssh-key is now not loaded anymore ( ssh-add -lshould return The agent has no identities.).

For your ssh-key to be automatically added to ssh-agent on first run of ssh we will create an alias.
But for this to work you will need to install and use “Powershell”.
It basically is an updated version of “Windows Powershell”.
You can install “Powershell” from the Microsoft Store.

We will now create an alias function for ssh to:
- check if ssh-agent has any identites loaded
- if there aren’t any identities loaded, load them
- execute ssh

For this alias to be persistent throughout sessions, we will add it to your user’s PowerShell Profile.

 if (-not (Test-Path $profile)) { New-Item -ItemType File -Path $Profile -Force | Out-Null }; notepad $Profile

Paste the following code into Notepad, save & exit and start a new “PowerShell” Session. (remember not “Windows PowerShell”)

function Private:ssh {param($params); (ssh-add -l | Out-Null || (ssh-add && Write-Host -ForegroundColor Green "ssh-key(s) are now available in your ssh-agent until you lock your machine!`n")) && ssh $params}

Important Note: Due to the way functions work in PowerShell, afaik it is not possible to have function parameters with dashes and without.
This means that commands like ssh -p 22 user@hostwill not work.
However you should probably use .ssh/config anyway if you need to specify other options on a regular basis.
All commands like ssh user@host will work without problem.

--

--