Linuxifying Windows for development
This guide is for 'linuxing-up' Windows as a development environment; it focuses on setting up WSL, an Ubuntu Hyper-V virtual machine, wsltty (a nice terminal emulator) and various tweaks.
Why use both WSL and a Hyper-V VM
For the same reason why the upcoming WSL version 2 uses Hyper-V – the i/o performance in WSL 1 is several-fold slower than in a VM, which means that build or install processes take longer.
WSL 2 is currently only available in Windows Insider Preview builds, so it's not suitable for users that aren't keen on being early adopters. Linuxifying Windows stable builds will be significantly more simple once WSL 2 is available.
Another notable perk of using a Hyper-V VM over WSL 1 is that the VM's state gets automatically saved when powering off the host, reducing disruption to development.
Why Hyper-V over VirtualBox or VMWare Player
Hyper-V's dynamic memory feature means that a smaller initial amount of memory can be reserved for the guest OS and then automatically increased if required (and also reclaimed later). In comparison, VirtualBox has a "memory ballooning" feature, but it can only re-distribute a fixed amount of memory between guests.
VirtualBox has better support for graphics acceleration in guests, but it's not required when the guests are used as headless servers.
Enabling Hyper-V prevents the use of VMware or VirtualBox versions prior to VirtualBox 6, because Hyper-V is a Type 1 hypervisor and reserves direct access to the hardware virtualization technology (VT-x or AMD-V).
Hyper-V makes Windows run as a virtualized guest, which adds a 9–12% CPU overhead and a 6–8% i/o overhead and can make a noticeable difference in resource-constrained scenarios (notably, games).
WSL and wsltty
choco install wsltty
optionalfeatures, select Windows Subsystem for Linux.
- Install the Fira Code font in Windows (contains various special glyphs)
- Run wsltty (called "WSL Terminal" in Start Menu)
- Right click wsltty window title and select Options
- Change theme under Looks (the default theme's blue is too dark to read on black; I use the flat-ui theme)
- Under Text, select Fira Code, increase size as required
- Under Window, increase the default columns and rows so that the window doesn't need to be resized each time
VS Code Remote Development
Install the Remote Development extension pack in VS Code and it'll allow to just seamlessly run
code . in a directory in WSL, and the launched VS Code instance will use tools like git from within WSL, allow running commands in WSL, etc.
Ubuntu Hyper-V virtual machine
- Windows 10 Pro (Home doesn't support Hyper-V), version 1809 or later
- Hyper-V enabled in firmware and supported by CPU
optionalfeatures, select Hyper-V.
Creating the VM
Run Hyper-V Manager, Quick Create…, select Ubuntu 19.04, follow the wizard, run the created virtual machine, finish initial setup with default settings.
The virtual machine is only connectable from the host OS by default; to make it connectable from the LAN, an external virtual switch needs to be created:
Hyper-V Manager, Actions, Virtual Switch Manager…, External, Create Virtual Switch, select the NIC connected to LAN.
Hyper-V Manager, Settings… for the created virtual machine, Network Adapter, select the created external virtual switch as the virtual switch.
To make the IP static:
Advanced Features under Network Adapter, select static MAC address radio option.
By default the VM will autostart with the OS only if the VM was running when the OS shut down; to make it autostart always:
Settings… for the created virtual machine, Automatic Start Action under Management, Always start this virtual machine automatically.
Sharing files with host OS
In VM terminal:
sudo apt install samba sudo vim /etc/samba/smb.conf
[homes] section and change
read only to
no under it.
sudo systemctl restart nmbd smbpasswd -a your_username
This PC, Computer, Map Network Drive, enter \\vm_host_name\your_username
VS Code Remote Development
- Install the Remote Development extension pack in VS Code
- Install Windows OpenSSH Client
ssh-keygen -b 4096from Windows command line and choose the defaults
- Copy the contents of
~/.ssh/authorized_keysin the VM
chmod 600 ~/.ssh/authorized_keysin the VM
- Go to Remote-SSH in VS Code, choose
%USERPROFILE%\.ssh\configand enter the VM host name
The same steps to set up SSH connections from Windows could also be repeated within WSL.
Running Ubuntu without desktop environment
sudo systemctl set-default multi-user.target
sudo apt install tmux in either the VM or WSL.
Windows shortcut target to automatically connect to a tmux session named 'main' in WSL:
%LocalAppData%\wsltty\bin\mintty.exe --WSL= --configdir="C:\Users\dabas\AppData\Roaming\wsltty" -~ -R o -e tmux new -A -s main
Windows shortcut target to automatically connect to a tmux session named 'main' in the VM (replace
%LocalAppData%\wsltty\bin\mintty.exe --WSL= --configdir="C:\Users\dabas\AppData\Roaming\wsltty" -~ -R o -e ssh -t <VM_HOST_NAME> "tmux new -A -s main"
Different icons can be set for the shortcuts to make telling the VM and WSL terminals apart easier when both are running.
In the end, now that VS Code supports remote development with containers (and descriptive files per project!), the best is to simply install the Docker Desktop program and run your development inside containers (so technically in the mobyvm Hyper-V OS).
A Hyper-V custom machine can be useful to test Linux specific features such as Kernel modules dependant programs. But a custom Hyper-V Linux with Docker can be hard to be configured to support host bind mounts making VS code remote development almost impossible.
When WSL 2 is released, running everything there with a good Docker integration can be interesting, although the performance will likely be the same as it is now with mobyVm.