Here is how I configure Windows Subsystem for Linux (WSL). I do things a bit strangely: by changing the mounts, by running a GUI Desktop, and by running Docker in WSL2 and not on the Host...
To get WSL on Windows 10 Pro, head over to Turn Windows features on or off and enable Windows Subsystem for Linux (WSL), which in turn needs Windows Hypervisor Platform (Hyper-V).
Set WSL to version 2:
wsl --set-default-version 2
Once that is done, open the Microsoft Store and download a WSL distro of your choice. I downloaded Ubuntu:
A new Start Menu entry for Ubuntu will be created, and on running it, a Ubuntu will be installed and prompt for a root username and password - I use
usr as the username.
After that, you will be dropped into a Linux prompt (
bash), in what is essentially a terminal window.
After my initial install, I did
wsl -l -v only to discover I was on WSL version 1. I probably ran Ubuntu once before
--set-default-version... if you have issues, follow Microsoft’s documentation, Step 4 - Download the Linux kernel update package and Step 5 - Set WSL 2 as your default version.
To upgrade the previously Downloaded distro:
wsl --set-version Ubuntu 2
Aside: I had a post sometime back, where I discovered VirtualBox running very slow after Hyper-V was enabled - the workaround is a boot menu to turn off Hyper-V in order to use VirtualBox. The two virtualization technologies do not play well together!
Cloning the instance
WSL2 creates a virtual hard disk (
.vhdx) for Ubuntu somewhere. So first thing I did was to copy the distro to a location of my choosing. This way I can muck about and then still fallback to the distro if anything goes wrong without having to delete (unregister) and download it again.
wsl --export Ubuntu - | wsl --import UbuntuDesktop [D:\VMs\UbuntuDesktop] - wsl -l
If you want to keep a clean copy of the distro, use
wsl --export Ubuntu ubuntu.tar instead. Using
- as above pipes STDOUT to STDIN, so that I bypass saving to a file.
You can set the new copy as the default distro:
wsl -s UbuntuDesktop
Or, start the distro explicitly (remember to specify the username, or else WSL defaults to
wsl -d UbuntuDesktop -u [usr]
Changing default mount behaviour
The default configuration mounts all Windows volumes as read-write. You can check with
mount which will list the Linux mount points mapping all Windows partitions, e.g.:
rootfs on / type wslfs (rw,noatime) ... C:\ on /mnt/c type 9p (rw,noatime,dirsync,aname=drvfs;path=C:\;uid=0;gid=0;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8) D:\ on /mnt/d type 9p (rw,noatime,dirsync,aname=drvfs;path=D:\;uid=0;gid=0;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8)
I prefer to explicitly allow / deny mounts, to limit read / write access, so I configure WSL2 not to mount any folders by editing
Now I can mount the specific folders I desire (the example below is as read-write, but you can add
-r to make it read-only). To automatically do this, I edit
sudo mount -r -t drvfs -o 'noatime,dirsync,aname=drvfs;uid=0;gid=0;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8' 'D:\VMs\UbuntuDesktop' /mnt/d
Finally, to allow mounting and unmounting without superuser password, add this to
usr ALL=NOPASSWD: /bin/mount usr ALL=NOPASSWD: /bin/umount
In limiting mount points and allowing only read-only access files (principle of least common mechanism?), I am breaking the principle of least privilege by allowing passwordless mount - so maybe do not do this! There may be a better way, I just have not figured it out...
I have a Linux drive in my system too, so I’ll update this when the next version of WSL allows
--mount-ing of physical ext4 partitions.
GUI apps via Remote Desktop
To run GUI apps without requiring to install an X Windows Server on Windows, I figured a Remote Desktop connection would suffice.
So, in the Ubuntu instance:
sudo apt update sudo apt upgrade sudo apt install -y xrdp xfce4
The installation of the XFCE Desktop and xrdp server took "864 MB of additional disk space" for me.
Just starting xrdp and connecting via Remote Desktop Connection client failed with the error below. I think it’s because the client is hard-coded to reject connections to
localhost on the default port, despite the fact that the local Remote Desktop Services service is not running...
To get things working, the minimum changes I needed to make before starting xrdp were:
sudo sed -i 's/port=3389/port=3388/' /etc/xrdp/xrdp.ini echo xfce4-session > ~/.xsession sudo service xrdp start
Now I can connect to
localhost:3388 via Remote Desktop:
In WSL1, a lot of things did not work including any browser I tried, e.g. Firefox would crash with
Channel error: cannot send/recv.
But WSL2 is great! I installed Firefox with
sudo apt install -y firefox and it ran just fine!
If I recall, at some point I also tried installing Google Chrome, and that worked too:
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt install ./google-chrome-stable_current_amd64.deb
Installing Docker Engine
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io sudo service docker start sudo docker run --rm hello-world
That worked for me and I got “Hello from Docker!”
Again this would never have worked in WSL1, I’d get errors like
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables -t nat -N and so on...
At this point you will have many, many Linux processes running in the background, even after you close Remote Desktop or logout from the console.
You could of course stop the running processes, e.g.
sudo service docker stop, etc. but otherwise, just remember stop the instance when you are done with it:
wsl --terminate UbuntuDesktop
Or terminate all running intances and the WSL2 VM itself with:
So that’s how my WSL2 Linux environment is setup.
Since I’ve stuffed my image with a desktop, UbuntuDesktop
ext4.vhdx image is almost 4.5 GB. That is nearing the size of my full Ubuntu Desktop 20.04 Hyper-V VM, which is 6 GB. I guess that makes sense, seeing that WSL2 uses Hyper-V...
But I still don’t understand why I can’t just manage WSL2 via the Hyper-V Manager. Wish I could just take a simple snapshot to rollback, instead of resorting to cloning the distro as previously mentioned.
On a final note, if like me, you mainly only run Docker... then perhaps Alpine Linux would suffice - remember that some commands do change slightly including
apk instead of
sudo is not installed,
service is not used etc.:
su - umount /mnt/c apk add --no-cache docker dockerd
You can go full inception with nested virtualization. I have tried Windows > WSL2 with Docker Engine > Ubuntu container with xrdp. Since everything is run in a container, then the WSL2 host volumes need not be exposed, so one could ignore the mount setup above. Maybe.