Sharing SSH keys between Windows and WSL 2
I recently wrote an article for Smashing Magazine that covers how I set up my personal development environment to use the Windows Subsystem for Linux version 2 (WSL 2). One of the things that I cover in that article is how to get SSH setup in WSL with Github. I mention in that section that you can share SSH keys between Windows and WSL, but I never showed exactly how to do it. There’s a good reason for that.
I couldn’t figure it out.
An SSH key is specific to a machine. Your machine. The problem is that the Linux distro you install in WSL see’s itself as it’s own operating system, and it wants its own set of SSH keys. The primary value propositions of WSL is that you can have both Linux AND Windows. As a developer, this is quite compelling as you can develop for both platforms on both platforms but with only one machine and without having to constantly switch OS’s. This means that you would need a set of SSH keys for Linux and one for Windows, ultimately treating your machine as 2 machines instead of one.
A better solution would be to share the same set of SSH keys between Windows and WSL so that you have one set of keys for one machine.
Setup SSH on Windows first
My recommendation is that you set up SSH on the Windows side first. Follow the instructions over on Github’s documentation to do this. It will walk you through generating the key, starting the agent and then adding your key to Github.
Copy keys to WSL
To use this same set of keys in WSL, you first need to copy them over. The keys are almost always located at
c:\Users\<username>\.ssh. That’s a folder. You will need to copy that entire folder from Windows, to WSL.
Open a terminal instance attached to WSL. Might I recommend the free Windows Terminal? You’ll love it. I promise. If you’re not 100% satisfied, you can get your money back – no questions asked.
Execute the following command to copy the keys from Windows to WSL.
cp -r /mnt/c/Users/<username>/.ssh ~/.ssh
Note that if you installed Github desktop, you do not need to setup SSH keys on the Windows side, and the .ssh folder will not be present. Make sure you follow the Github instructions above to generate the SSH keys on Windows.
If you were to try and push something to Github from WSL, it will warn you that it doesn’t recognize the remote host and it will ask you if you want to connect. Type “yes”. Then you will get an error that looks something like this…
Like nearly everything that goes wrong on Linux, this is a permissions issue. You need to adjust the permissions on the key file to get this working. To do that, run the following command from WSL.
chmod 600 ~/.ssh/id_rsa
What this does is set Read/Write access for the owner, and no access for anyone else. That means that nobody but you can see this key. The way god intended.
Now try and push to Github…
Now, you will be asked to enter your passphrase every single time you try and push to Github. That’s going to get old in a hurry. This is because the ssh agent isn’t running on the Linux side. To get the agent running when WSL starts, first install keychain.
sudo apt install keychain
Then add the following line to your
eval ``keychain --eval --agents ssh id_rsa
Each time you reboot, you’ll have to enter your passphrase. But you only have to do it one time until you reboot or terminate WSL.
There are other ways to auto-start the ssh-agent in WSL. There are instructions in this article that show how to do with with Zsh.
Sharing is caring
While you can set up SSH keys on both the Linux and the Windows side, it feels a bit redundant. It also feels a bit like I’m not utilizing the full potential of WSL, which is that it lets me move between the two operating systems as if they were one. Sharing the same set of keys feels a bit more like I’m on one system instead of two.
I care because I’m always looking for the one “right way” to do things. The reality is that there is no one “right way” to do anything. You can setup SSH keys on both WSL and Windows, or you can set them up just in Windows and share them with WSL. It’s your world. The ssh keys just live in it.
I made a bash script to simplify this process and allow me to run it on startup (with support for ignoring SSH sessions). It is available on GitHub here: https://gist.github.com/emabrey/034c399f087263a6ab6cc860a314a486 . Word of warning- I have not tested this on WSL 2 yet. It also will clobber your
shopt nullglobsetting, though it should be fairly simple to use
shoptto save/restore state if that is important to you. I wrote and use this on a Debian install, so I do not know how well it will transfer to other linux installs/versions of SSH/etc.