Windows Subsystem for Linux is now a mainstream Windows 10 feature available in the Windows Store. If you didn’t take a look when it was in beta then you should now.

Note – this post is an updated, self-contained guide to using WSL on Windows 10. My first post about WSL gets into its early development and describes the sort of tasks I use it for, but you don’t have to read it first to understand this post.

What is WSL?

Screenshot: WSL showing windows and ubuntu details

WSL is a fully featured bash shell on Windows 10, with interoperability between the CLI and Windows GUI. The WSL+Win10 developer experience is broadly the same as OSX+Terminal, although Microsoft is also integrating WSL with Visual Studio for those who prefer the Microsoft GUI dev style.

WSL is not a virtual machine, it’s a Linux-compatible Windows kernel that can run Linux binaries. That makes it much lighter than a VM as you’re not running entire virtualised operating systems. Superficially it feels a little like running Docker images, although they seem more likely to integrate than compete.

WSL instances are so cheap to run on the system that I’m currently running Ubuntu and openSUSE sessions side by side, just to avoid the relatively minor hassle of configuring different SSH keys. This is not something I’d do with full VMs.

Is WSL ready for prime time?

Yes. A year ago when I wrote about WSL beta, it was missing key features. They were steadily added to Insider Preview builds, and eventually released to mainstream Windows 10 in April 2017. More polish, multiple Linux distributions and simple installation just arrived in the October 2017 Creator’s Update (MS somewhat short-sightedly call it the Fall Creator’s Update).

WSL is a serious option for development. I regularly use it for NodeJS-based projects; and work on the same codebase in OSX without round trip issues. It really is a proper bash environment for Windows!

The main caveat is that some test suites need hacks or workarounds to work with WSL, eg.

  • Karma needs you to manually open the server in a browser tab (it doesn’t capture it automatically)
  • Some finicky path and filename hackery is required to get Selenium working in WSL with Windows 10 browsers. Hopefully this will be resolved in future, even if only in headless browsers; or perhaps with ways to get GUI browsers running inside WSL.

Currently it’s easier to drive Selenium tests from WSL against hosted options like Saucelabs, or rely on tests running on your CI server. Both are common practices so this may not be an issue for your team at all.

I will also note WSL needs UTF-8 rendering improvements. It doesn’t matter for common dev tasks, but might be a problem if you rely on a lot of unusual characters.

Changes from beta WSL

If you’ve never used WSL before you can skip this bit and go straight to First Time Install.

There’s a full change list in Microsoft’s blog post but some key things to note…

Beta install deprecated

Since the Fall Creators Update in October 2017, MS have deprecated the old version of WSL. The old one will still work, but they recommend you uninstall the beta Ubuntu and reinstall via the Windows Store.

To uninstall a beta version of WSL:

  1. (optional) Make a backup of your home directory: rsync -r ~ /mnt/c/wslhomebackup
  2. Open cmd.exe and run lxrun /uninstall /full

New home directory location

The new home directory location is:

C:\Users\WINDOWSUSERNAME\AppData\Local\Packages\PACKAGEDIR\LocalState\rootfs\home\LINUXUSERNAME

PACKAGEDIR will include the package name and some ugly installation hashes. On mine the directory names start with CanonicalGroupLimited.UbuntuonWindows and 46932SUSE.openSUSELeap42.

Official name is WSL

A small but nice thing to note is MS have stated they will not talk about “Bash on Windows” or any other variation of that theme any more. This mostly matters because it was really hard to google anything about it. From here on the official name is Windows Subsystem for Linux, or just WSL.

First time install

Screenshot: Linux distributions in the the Windows Store

If you haven’t used WSL before:

  1. Go to Turn Windows features on or off
  2. Enable Windows Subsystem for Linux
  3. Reboot. You actually do have to reboot for this one.
  4. Search for linux in the Windows Store, choose your distribution (Ubuntu if in doubt) and install it
  5. Once installed, run it and enter the username and password you want to use. Put these details in your password safe, you will need the details for installing updates.

Microsoft provide a detailed installation guide if you hit any issues.

Tips

Don’t cross the streams

Run dev tools and compile things in WSL or Windows, but don’t try to straddle the two worlds. For example do not install NodeJS on Windows then try to use it inside WSL, or run npm install on Windows then try to run your app in WSL (Linux will be trying to execute dependencies compiled for Windows).

The good news is you have absolutely no need to switch between the two for dev tools. The usual pattern here is:

  • Git clone, install and run your app in the CLI (WSL)
  • Use Win10 for a GUI text editor and browsers

You can edit and move files around in either one, so long as you don’t cross the file system boundaries.

Understand the file system boundaries

You can edit Windows 10 files in both Win10 and WSL, but you can’t edit WSL files in Windows 10. By WSL files I mean files contained within the WSL file system, located at:

C:\Users\WINDOWSUSERNAME\AppData\Local\Packages\PACKAGEDIR\LocalState\rootfs\

...noting your home directory is home\LINUXUSERNAME under rootfs.

Windows 10 files are, well, everything else.

WSL makes it hard to accidentally edit things you shouldn’t, for example if you try to launch your home directory in File Explorer it takes you to C:\Windows\System32 instead of its real location. If WSL’s root directory moves for some reason, a simple trick is to create a distinctly-named file in your home directory (eg. touch ~/jozxyqk.txt) and then use Windows file search to locate it.

In practice it doesn’t matter. Configure a working directory in the Win10 file system and you’ll be fine.

Configuration

My configuration suggestions presume you don’t work 100% in bash; and like to be able to switch between the CLI and GUI while coding. This is what I’ve observed the majority of developers doing over the years, barring a few really hardcore vim devotees.

This configuration puts your working directory (where you check out code and work on it) outside WSL’s file system, leaving only bash config files inside. You will still need to use something like vim or nano to edit ~/.bashrc, ~/.gitconfig, SSH keys, etc; but for daily dev you don’t have to think about the file system boundaries.

Getting to it:

  • Create a working directory outside WSL. Mine happens to be /mnt/f/dev (f:\dev).
    • Don’t use your WSL home directory as that crosses the file system boundaries.
    • Don’t use your Windows home directory (C:\Users\USERNAME) as that can clash with other shells like Git Bash.
  • Create a bashrc file somewhere in the Windows file system; and execute it from the WSL bashrc. For this example we’ll create f:\.bashrc. In WSL:
    • run echo 'echo "My WSL settings are working"' >> /mnt/f/.bashrc
    • run nano ~/.bashrc and add source /mnt/f/.bashrc at the end. Don’t remove the stuff that’s in there already. If you’re not familiar with nano, save and exit with ctrl+x (exit), y (confirm save), enter (accept filename).
    • Close and restart WSL – you should see “My WSL settings are working” echoed. You can now put your usual bash config into f:\.bashrc and edit the file in any editor, without crossing the file system boundary.
  • Optional: run echo "cd /path/to/dev" >> /mnt/f/.bashrc so you always start in your working directory (simple but effective).
  • Optional: create new SSH keys inside WSL and cat them out for other systems.

Useful aliases

  • alias open="explorer.exe" – usage open . to open current location in File Explorer.
  • alias s='"/mnt/c/Program Files/Sublime Text 3/subl.exe"' – note the double quoting to get around the spaces in the path. Usage: s filename to open in Sublime. This should work for any editor that accepts CLI arguments.
  • alias ls="ls -la --color --group-directories-first" (if you ever want to run stock ls, just escape your alias by running \ls)

OS detection

  • You can detect WSL with grep 'Microsoft' /proc/sys/kernel/osrelease
  • You can detect the specific distro using cat /etc/*-release | grep ^NAME

I have a bash OS detection script on Bitbucket if you need it.

Git bling between distros

Ubuntu and openSUSE have different git versions, so your git bling might not work in one or other if it checks for the full 'nothing to commit’ string that differs on working tree vs working directory. So ensure you just check the common substring:

parse_git_dirty() {
[[ $(git status 2> /dev/null | tail -n1) == *"nothing to commit"* ]] || echo "(*)"
}

I have a WSL compatible git bling script on Bitbucket if you need it.

Maintenance

You need to keep WSL instances up to date. When you start up they will prompt with a message that updates are available. The commands to run are:

  • Ubuntu: sudo apt-get update && sudo apt-get -y dist-upgrade
  • openSUSE: sudo zypper --non-interactive update && sudo zypper --non-interactive refresh

I expect there will be other Ubuntu/openSUSE differences so it’s a good reminder to include the distro name when looking for help and documentation. You can get distro details by running cat /etc/*-release.

Last thoughts

For years in the web development world, Windows was a second-class citizen at best. The tools all ran in bash, and Windows just wasn’t at that party.

You could get by with tools like Cygwin and the tweaked Node.js command prompt, but even so you’d still spend a lot of time just trying to keep things working. Often more time trying to keep things working than getting work done.

When Microsoft opened their console improvement project to feedback, the message was overwhelmingly 'give us bash’. I was one of many who gave feedback, although I have to admit I didn’t hold out any real hope. I’d long since switched to OSX at work, and thought Microsoft had simply tapped out of the open web to focus on the .NET ecosystem.

Sometimes it’s really nice to be wrong :) It’s been refreshing to see the way Microsoft embraced the community feedback and ultimately delivered a great solution. The WSL project has been open and responsive – raise or comment on an issue in github and you’d see direct feedback from the team, usually within a few days. You can still provide feedback on UserVoice too.

The project itself has changed my expectations of Microsoft. It's easy to be cynical, but devs asked for bash and Microsoft were willing to put Linux into Windows to do it. Recent backpedalling aside, can you imagine that happening in the Ballmer era? Times have certainly changed.

It's actually OSX that lags behind for bash. Apple still ships Bash 3 (released in 2007), generally thought to be a result of the company's open source licensing policy. You can update individual systems to Bash 4, but it doesn't help because any shared script still needs to be Bash 3 compatible.

WSL seems to have reached a milestone from Microsoft’s point of view, as they’ve made some organisational changes aligning WSL with Hyper-V and Containers. This sounds like the big initial push is done and WSL will be in more of a business-as-usual mode from here on. That's hopefully just a sign of the project moving into a different phase.

I hope WSL is here to stay. I love the levelling factor of bringing relatively cheap PCs back into the game for web development. I also enjoy the sheer strangeness of Microsoft putting Linux on the desktop for millions of people. But most of all I like the fact it has brought my home PC back to being a serious dev tool and not just a testbed for browsers.