We’re fans of Linux in the office, but often have to use Windows in our day-to-day work. The idea of having a fully-functional Linux distribution available within Windows is pretty appealing—does WSL 2 fit the bill?
WSL 1 was a good start; it offered full emulation of kernel calls, allowing us to run full Linux apps in Windows. WSL 2 is something of a rewrite and instead of emulation it (initially) includes a full 4.19 kernel with a Hyper-V virtual machine running underneath the hood to provide support.
What follows is a deep dive on installing and setting up a WSL 2 environment with Visual Studio Code, with some added extras thrown in (Oh My Zsh, Powerline). We’ll cover some extra tooling (Docker, Cypress) in a future blog post. Grab a coffee, it’s a long read.
If you’re interested in setting up a WSL 2 development environment, there are a few pros and cons to be aware of:
- This executes code inside WSL; if your code doesn’t run in Linux it won’t work (for example, .NET Core will work but .NET won’t!)
- It’s (largely) command line only. If you’re a Linux fan, this hopefully isn’t an issue
- It’s not as fast as an on-metal Linux install; you won’t get the same benefits as (for example) running docker on Linux just because you’re in a Linux VM
- Whilst file access is faster in WSL 2,
/mnt/c
access (or, ‘access to your normal Windows file system’) is much slower in WSL 2 than it was in WSL 1. Part of the change to a full Linux kernel is the requirement to pass through an API layer when making file system calls to windows, making everything slow. If you plan to develop, make sure your code is in the Linux filesystem! See this github issue for more - Enabling Hyper-V virtualisation gets in the way of a few other VM engines (VMware, VirtualBox before 6.0), though compatibility is being improved over time
- Some hardware support is limited for now (e.g. GPU)
- Although Hyper-V isn’t available on Windows Home edition, WSL 2 will still work
- Encapsulating your development environment (whether in a docker image, a VM, or WSL) has some great benefits, particularly when working with messy installs like Python. The ability to backup, or to trash and start again cheaply can make a big difference
- Upgrading WSL 1 distributions is easy and just takes a minute or two
We’ll take you through the necessary steps to get WSL 2 up and running.
Install WSL 2
WSL 2 is now available on the mainline Windows 10 release via the update channels (release 2004). No need to be on an insider built to try it out anymore!
If you’ve already got WSL 1 running on your machine there’s no harm following the instructions; some of these are different from a WSL 1 installation and aren’t optional!
The full WSL installation docs are available here if you have issues. I’ve reproduced a slimline version below.
Open an administrator level PowerShell window and run
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
Note that if you have installed WSL before, that second line is new and is required.
That ensures that WSL is running, and that WSL 2 has access to the VM platform it requires. Restarting at this point is a good idea, if you don’t you’ll hit a fairly obscure error message.
Go to the Windows app store and download an image of your choice (I’ve tested on Ubuntu 18.04, but others should work). Depending on your existing setup, you may find these are running WSL 1 by default and so need to change to WSL 2.
WSL 1 Upgrades
In PowerShell again, run
wsl -l -v
Existing WSL 1 distributions will be visible in this list as well as newly downloaded ones, and either can be upgraded. If all of your images already show as v2, skip to the next section!
Tip
WSL 1 and WSL 2 images can run side-by-side, and there’s no harm to downgrading images if you’d like to go back to WSL 1
For v1 distributions, take the name of the distribution and insert it into the command
wsl --set-version <Distro> 2
This command may take a few minutes. At this point it’s worth making sure future distributions are all started on v2 by running
wsl --set-default-version 2
To check that it’s upgraded, run
wsl -l -v
If it’s not, try:
- Ensuring that you ran the line in PowerShell that uses DISM to enable the feature VirtualMachinePlatform
- Restarting, if you haven’t already
- If you get a message about installation failing, ensure that virtualisation is enabled in your BIOS. This is BIOS-specific, so seek guidance!
Tip
Installing WSL will put the system bash.exe
higher on the path than other copies (like git-for-windows bash). If this is an issue for you, change your path variable to put your git copy of bash.exe
before C:\Windows\System32
Oh My Zsh and Powerline (Optional!)
We’re also big fans of Zsh. This is entirely optional, but if you’d like to run Zsh and Powerline, follow along. Otherwise, feel free to skip to installing VS Code.
Start up the WSL shell. This can be done by:
- Running the app store installed distribution directly (an app called ‘Ubuntu’ on my machine)
- Running a terminal of your choice, and executing the bash copy in
C:\Windows\System32
(I like either the Hyper terminal or the new Windows Terminal – note that I’ve found the Windows terminal to be easier to work with when we get to Powerline below!)
Once inside (if it’s the first launch), you’ll be asked to set a password.
sudo apt update sudo apt upgrade sudo apt install zsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" chsh -s /usr/bin/zsh
Tip
There are a few nice Zsh recommendations that we don’t want to deal with in detail. Take a look at the following:
- There are a lot of nice colour schemes available for the terminal which work with Zsh; we particularly like Solarized Dark
- You probably want to update your DIRCOLORS to match your theme
- If you use one plugin to start, we recommend the excellent
z
, which makes warping to previously used directories trivial
At this point we’re going to install Powerline, but we’ll use a fast re-implementation called Powerlevel10k. It’s got a few performance savings that will help us whilst running in the VM!
Before we do that however, we’ll head back to Windows and grab some fonts to help us render Powerline properly. Any set of font referred to as ‘nerd fonts‘ will work, and we’ll use the excellent Delugia Nerd Font. Grab the .complete.ttf
version, and install it right-clicking on it in Explorer and selecting ‘install’.
Back to the WSL terminal, to install Powerlevel10k just create a subfolder to keep the install folder in and then run
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git $ZSH_CUSTOM/themes/powerlevel10k
Then open up your Zsh config (nano ~/.zshrc
, or an editor of your choice) and include the line ZSH_THEME=powerlevel10k/powerlevel10k
.
When next launched (or by running source ~/.zshrc
) you’ll be taken through a set of preferences to set up Powerline. If you’re running hyper.js and seeing issues (particularly with kerning), try Windows Terminal instead. If using Windows Terminal, you’ll need to override the font used. Go into your settings and add a "fontFace": "Delugia Nerd Font"
line to the WSL profile object.
Install Visual Studio Code
We don’t actually want to install VS Code in WSL—we’ll be using the new remote features to run code in WSL from a Windows instance. For more information check out this article. TL;DR? It just works, even to the point of intelligently installing extensions on the appropriate OS depending on usage.
- Install VS Code on Windows. When prompted to ‘Select additional Tasks’, check ‘Add to Path’. This was default for me, so you likely don’t need to reinstall if you already have VS Code
- Inside VS Code (launched via Windows), install the extension ‘Remote Development‘.
- Set VS Code font via File -> Settings -> Features -> Terminal. Set the font family to ‘Delugia Nerd Font’
- Back in WSL, just navigate to a code folder and type
code .
et voilà! One Windows-based instance of VS Code, executing code inside WSL.
Before we get to actual code, it’s worth referring to a few handy hints and tips from the VS Code team:
- Linux uses different line endings, we don’t want git to think you’ve made edits to every line in your app when you move to Linux! Check this article out.
- If you also develop in Windows, you shouldn’t try to maintain two different sets of git credentials. See how to use a single set of credentials in this article.
As mentioned in the pros/cons list above, WSL 2 is slow when accessing a lot of files on the Windows filesystem. Simple git tasks like status will be noticeably slower. To avoid this, move your code folder into the Linux filesystem. Either:
- From inside the WSL shell,
mv X Y
where X is your current code folder (find your C: drive inside\mnt\c
), and Y is a folder in Linux (for example~\Code\Project Name
might be a good place!) - From Windows, navigate to
\\wsl$\
. This shared drive represents your Linux filesystem. Files and folders can be copied straight into here. To find your home folder (~
), just navigate to\\wsl<distroname>\home<username>
Note: the Linux filesystem is also available within your appdata folder, but it’s important to only access it via the shared drive. That allows Windows to intercept file calls and translate them to the Linux file system, preventing painful issues when accessing or modifying data!
Tip
We glossed over it pretty quickly above, but \\wsl$
is a great way to access your Linux filesystem from Windows. It’s the only safe way to access it (do not access it directly, we won’t even tell you where it is to avoid you going looking for it).
At this point the system is up and running. You’ll need to set up your development environment. For us that involves:
sudo apt install curl // Note the zsh below! If using another shell, replace zsh (e.g. with bash) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | zsh nvm install --lts node --version npm --version
Note that we grabbed nvm version 0.35.2 (latest at time of writing), check here to see if a newer version is available!
The last two commands should print out installed versions if the process worked.
And with that you’re up and running. Clone a code folder, run code .
and start developing. In the next blog post in this series we’ll handle running Docker and Cypress within WSL 2.