SSH key and the »Windows Subsystem for Linux«

With Bash on Ubuntu on Windows, you can use a Windows Subsystem for Linux on Windows 10. With that, you can run many Linux commands, for example, ssh. This post shows you how to create an SSH key, which should be used on both, the Linux subsystem and Windows.

Update from May 14, 2018: After updating to the Insider Build 17063, you need to run the following commands on the Windows Subsystem for Linux to make the solution work again, as Entity Black points out in his comment under this post:

sudo umount /mnt/c
sudo mount -t drvfs C: /mnt/c -o metadata 

Update from May 29, 2018: It seems that the steps with unmounting are only temporary, as pointed out in the comments. To fix this, you need to modify or create a config file and add a little bit of content to it. There are three slightly different ways proposed in the comments – one by Andrew, one by Entity Black, and one by Vince.

Update from July 10, 2018: Darren mentioned in his comment, that using SSH alias with the described solution will fail, and how to solve that.

Goal

I wanted to create an SSH key, which I can use with the Linux subsystem and standard Windows programs. In the best scenario, the key is stored only once on the hard disk. You can read a tutorial about installing the subsystem on howtogeek.com.

Solution

The default path for SSH keys on Windows is C:/Users/Florian/.ssh which matches the path /mnt/c/Users/Florian/.ssh on the Linux subsystem. Default SSH path on the subsystem is ~/.ssh.

Previous to this post update, I had a not optimal solution where the keys needed to exist twice. But in the comments there were several folks with better solutions – one of them Andrey Chirkov, who posted a one-line solution that you run on the Windows Subsystem for Linux (the ~/.ssh folder must not exist before running it):

ln -s /mnt/c/Users/Florian/.ssh ~/.ssh
Code language: Bash (bash)

That creates a link from ~/.ssh to /mnt/c/Users/Florian/.ssh. With that, we only need to store our SSH keys in the Windows path and can use them from the Linux shell, too.

After trying it, I noticed that this line was also part of the Stack Overflow response I linked in the previous version of the post. I have no idea why I did not get it working back then…

The original version of this post was published on March 8, 2017.

37 reactions on »SSH key and the »Windows Subsystem for Linux««

  1. Thanks!

    I also found I could copy existing Windows keys and then fix up the permissions with:

    chmod 600 ~/.ssh/id_rsa
    chmod 644 ~/.ssh/id_rsa.pub
  2. Thank you for your help ! Your article helped me to figure out how the whole ssh system worked.
    Just one thing : the private and public keys were created in the root/.ssh directory in my case, and not in the user directory. But I use the Linux subsystem for Windows, so that can be an explanation.

  3. Have you tried hard-linking the files rather than using a symbolic link? I think the permissions would be preserved in that case.

  4. This works for me and I have just one key 😉

    ```
    ssh-keygen -t ecdsa -C "" -f /mnt/c/Users//.ssh/
    touch ~/.ssh/config
    vi ~/.ssh/config
    ```

    **paste:**

    ```
    Host *
    IdentityFile /mnt/c/Users//.ssh/id_ecdsa
    ```

    **save config**

    ```
    chmod 600 ~/.ssh/config
    chown $USER ~/.ssh/config

    touch /mnt/c/Users//.ssh/known_hosts
    ln -s /mnt/c/Users//.ssh/known_hosts ~/.ssh/known_hosts
    ```

    1. Hi, I've got the sim link set up ok. Trying to ssh gives me a permission error. "0777 for .... are to open"

      I cant seem to chmod the files. When run (sudo or user) the permissions don't change - and no error is given.

  5. Guys have you tried multiple ssh keys ?

    I have 2 keys,

    home_rsa
    work_rsa

    but even if I modify the config file, they do not get picked up, I always have to rename it to id_rsa for git clone to work.

    Anyone else noticed this problem?

  6. Hi Florian,

    thanks for the link, that solved the issue. Indeed the default SSH Agent does not work so well with multiple keys.

    Best,

    Miha

  7. Important update,
    based on latest update "Insider Build 17063" there has been significant change in permissions. In very short, you need to:

    sudo umount /mnt/c
    sudo mount -t drvfs C: /mnt/c -o metadata

    Relevant links:
    https://github.com/Microsoft/WSL/issues/3181
    https://blogs.msdn.microsoft.com/commandline/2018/01/12/chmod-chown-wsl-improvements/
    https://blogs.windows.com/windowsexperience/2017/12/19/announcing-windows-10-insider-preview-build-17063-pc/#cbUAtBrErr1A3JJA.97

      1. I found the solution.
        Since I wasn't able to mount c: with metadata flag I had to change /etc/wsl.conf and include the following:
        [automount]
        options = "metadata"

  8. It worked once after unmounting and remounting drive C. When I exit and re-enter the shell, I'm once again unable to use git.

    This isn't a workable solution for me. I need to do some reading to find out what the change was (something with the drvfs mount type?) and how to make it permanent.

  9. Okay, it was easier than I thought.
    The solution that worked for me was to add a very simple /etc/wsl.conf:

    [automount]
    enabled = true
    options = "metadata"

    I found part of the answer at Stack Exchange's Super User site:
    https://superuser.com/a/1295442/280338

    ... but that answer resulted in fixed directory permissions and ignored file permissions for me.

    I read the referenced MS page:
    https://docs.microsoft.com/en-us/windows/wsl/wsl-config#set-wsl-launch-settings

    ... but using that code resulted in not mounting the host drives at all. Using just the enabled and options parts from the page resulted in fixed directory and file permissions, which kinda works, but I'd rather set the permissions myself.

    Then I remembered that the temporary solution from here only sets the "metadata" option. So, that's what I did, and it works like a charm... Just like I have a real operating system with a real filesystem.

  10. @Andrew, Entitiy Black and Vince: thanks for your additional comments! I will add an additional update box to the beginning of the post pointing to the comments section with your tips 🙂

    Best,
    Florian

  11. Hi,
    It may be worth noting that if using the ssh configuration file, you may need to do this a slightly different way.
    Due to strict permissions requirements of the .ssh/config, it requires it be only read/write on that file. Thus it cannot exist on the windows file system. A way around this is to simply use symlinks to each individual key file and known hosts, and let config reside on the linux side.

    Thus, using
    ln -s /mnt/c/Users/YourName/.ssh/id_rsa.pub ~/.ssh/id_rsa.pub
    ln -s /mnt/c/Users/YourName/.ssh/id_rsa ~/.ssh/id_rsa
    ln -s /mnt/c/Users/YourName/.ssh/known_hosts ~/.ssh/known_hosts

    And then leaving the .ssh/config file as-is, not symlinked on the linux side, with permissions 600, allows for usage of the .ssh config file. Thus, you can have quick alias names in there such as:
    Host myAlias
    HostName somewhere.com
    User exampleUser

    And can easily connect with:
    ssh myAlias

    If you symlink the entire .ssh folder, and have a config file in there, windows takes over the ACL and you can no longer specify a 600 permission. Thus, trying to connect via the alias will result in a failure due to incorrect permissions. This is what wound up working for me anyhow. Hopefully it helps someone else out setting this up!

    1. Hi Darren,

      thanks a lot for your comment! Personally, I did not use alias yet, but it is good to know 🙂 I will add a link to the update box at the beginning pointing to your comment.

      Best,
      Florian

    2. Darren,

      Your comments about "strict permissions requirements" of .ssh helped me investigate my password-less ssh login issues with the Windows Subsystem for Linux (WSL). Also, your comments about the permissions and which side controlling the file permissions was helpful. But my solution was a bit different and, in particular, the use of the ln command was different.

      My approach was to allow the WSL to control the file permissions of /home/comperem/.ssh and everything in there (known_hosts, id_rsa, and id_rsa.pub)

      Previously I had changed the WSL bash HOME environment variable to /mnt/c/Users/comperem by editing the WSL system-wide bash.bashrc file in /etc/bash.bashrc with this:
      export HOME=/mnt/c/Users/comperem

      Then, in WSL's bash, after running 'ssh-keygen -t rsa' and hitting return to all defaults with no passphrase, the WSL files appeared in their expected location with proper permissions:
      ls -l /home/comperem/.ssh/
      total 4
      -rw------- 1 comperem comperem 1679 Jul 21 11:46 id_rsa
      -rw-r--r-- 1 comperem comperem 397 Jul 21 11:46 id_rsa.pub
      -rw-r--r-- 1 comperem comperem 444 Jul 21 11:46 known_hosts

      Notice the permissions properly implemented with WSL's bash: -rw-r--r--

      This is where my solution differs. The ln command is similar to the cp and mv commands:
      ln -s src dest (or ln -s TARGET LINK_NAME which is the same conceptually)

      Creating a symbolic link to .ssh in the Windows home folder to the WSL .ssh with:
      ln -s /home/comperem/.ssh /mnt/c/Users/comperem/.ssh

      results in the proper permissions for the entire contents of the .ssh folder on the WSL side:
      comperem@matrix:~/.ssh$ pwd
      /mnt/c/Users/comperem/.ssh
      comperem@matrix:~/.ssh$ ls -l
      total 4
      -rw------- 1 comperem comperem 1679 Jul 21 11:46 id_rsa
      -rw-r--r-- 1 comperem comperem 397 Jul 21 11:46 id_rsa.pub
      -rw-r--r-- 1 comperem comperem 444 Jul 21 11:46 known_hosts
      comperem@matrix:~/.ssh$

      Then remote login with ssh is passwordless via the public keys as expected.

      My solution is a bit different but your post helped.

      1. Hi Marc,

        I received two almost identical comments from you (I think the second had one more line of code) – I replaced the comment text of the first one (that was marked as reply to Darren) with the text of the second one, so it is correctly listed as a reply here and includes your modification 🙂

        Best,
        Florian

  12. sshd -ddd complained bad owner or modes for /mnt/c/Users/user initially, so I did chmod 755 /mnt/c/Users/user. Again, sshd compalined about the permission stuff for /mnt/c.

    I turned off strict modes to get a simple workaround. Though it's not a good way to do it, this and the metadata thing together can get public key auth work on the current wsl.

    Maybe keeping two copies of .ssh is in fact the best painless solution. This is what I feel after a whole struggling.

  13. Thank you for this article and the comments.

    Reading here and there, the solution I came with is:

    sudo umount /mnt/c
    sudo mount -t drvfs C: /mnt/c -o metadata

    To make the change permanent, edit /etc/wsl.conf:

    [automount]
    options = "metadata,uid=,gid="

    To use the config file in ssh, I simply restrict the permissions on this file to read-only on Windows.

  14. Best article on the internet for this topic. Finally got Subsystem linux and ssh and windows working in harmony! Hallelujah!

Leave a Reply

Your email address will not be published. Required fields are marked *