Adding Windows Subsystem for Linux on Windows 10

After a recent Windows 10 security update, the cygwin installation stopped working, as mintty was unable to fork bash. The last time this happened, none of the nostrums on the internet had worked, and a complete re-install was required. However, this time I had an alternative, Windows Subsystem for Linux (WSL).

I'd been watching its progress for a while and now that, in the Fall Creator's Update, the use of network shares had been enabled, it seemed to have the features I needed.

First, you have to turn on WSL via the Settings->Apps & Features->Related Settings (Programs and Features)->Turn Windows Features on or off and tick the box labelled Windows Subsystem for Linux. A reboot will be required.

Once enabled, I discovered that Debian was now available for WSL - much better than Ubuntu. Installing was a matter of moments from the Microsoft Store. Pretty much all the configuration information it needs is a user name.

Now, I needed a decent terminal emulator to front it. It turns out that mintty has been forked for WLS, named wsltty (natch). This was also a simple install.

Once fired up, I was presented with a bash prompt. The first things to do were to

  sudo apt-get update
  sudo apt-get upgrade
  sudo apt-get install python ssh rsync mg

mg is a lightweight terminal-only version of emacs, which I prefer to use rather than vim, which is included. Linux-based editing tools are necessary because you must not edit Linux files with Windows tools, as the Windows tools do not handle the Linux file metadata. See this graphic warning.

NOTE: Things have changed recently. See these chmod improvements. Furthermore, automount options can be specified in /etc/wsl.conf. See this. However, the WSL version I have doesn't contain these capabilities.

My first (and presumably not the last) footshooting incident occured when I edited the /etc/sudoers file in an attempt to remove the need for entering a password when running sudo. The result was that I introduced a syntax error and sudo cried out in horror and refused to run. Now what? Advice on the internet either involved tools that did not exist on the WSL Debian install, or required booting into single user mode. However, there is a simple workaround. It is possible to set the default user name when WSL is started. The normal default is the user name entered as part of the installation.

I figured I could change the default user to root (hopefully no password required) and fix the syntax error. The debian executable is located in C:\Users\mark\AppData\Local\Microsoft\WindowsApps.

  debian config --default-user root

I restarted Debian and was in as root. Foot unshot.

To make the WSL enviroment comfortable, I wanted to have my Windows home directory be the Debian home directory. By default, the home directory for the default user is under /home, as one would expect. Initially, I tried making /home/mark a soft link to /mnt/c/Users/mark/home. This worked, but then the ssh client was unable to use my certs, as it is not possible to set the file permissions on a file in the Windows file system as ssh expects, due to above file metadata issues.

The compromise I made was to leave /home/mark as my home directory in /etc/passwd, then place the .bash_profile file, plus the .ssh directory in /home/mark. In /home/mark/.bash_profile, I set the HOME variable to the Windows home location:

  export HOME=/mnt/c/Users/mark/home

This seems to do what I need. Bash thinks my Windows home is my WSL home and the ssh client is still using /home/mark/.ssh to access the certs, as it ignores the value of $HOME value and directly accesses /etc/passwd.

The last useful piece of setup was related to the ability to right-click in a folder window and invoke bash with the folder as the current working directory. This involves setting up Windows registry entries to add the appropriate menu items. wsltty provides scripts for to put the entries in the Windows registry. However, subverting the default rcfile name was the only way I could find to make bash behave as a login shell and still use the selected folder as the current directory.

  %LOCALAPPDATA%\wsltty\bin\mintty.exe --WSL="Debian" \
    --configdir="%APPDATA%\wsltty" /bin/bash --rcfile /home/mark/.bash_profile

Network shares

Network shares can be mounted like this:

  sudo mount -t drvfs '\\crimson\public' /mnt/share/crimson/public

I tried using rsync to synchronise my home directory to a directory on the share. Even with nothing to update, it took 4 minutes 30 seconds. By contrast, rsync under cygwin, also with no updates required, took 49 seconds. I/O through drvfs must be very inefficient.