Development environments can be notoriously difficult to set up. They often involve managing tools and dependencies required for different projects, meanwhile organising them in a way that doesn’t break compatibility or worse, your own system.
While admittedly some of the best setups are *nix-based, this blog post aims to establish how to make the best out of *nix tech on a Windows machine using three main building blocks – Hyper-V, Windows Terminal and VS Code.
At the core of this setup is Hyper-V, Windows’ native hypervisor. It lets users dedicate a part of the underlying hardware to virtual machines (VMs), leveraging secure virtualization supported by many modern processors. To enable virtualization, check your machine’s BIOS settings – e.g. for AMD chipsets this is called SVM mode.
There are a few benefits from using VMs. Firstly, all of your development work now runs in isolated cores and uses a dedicated part of memory not in use by anything else. Because of how Hyper-V handles virtualization, you can set checkpoints and restore your VM to any previous checkpoint – handy for experimentation with ample room to roll back!
If you’re on Windows 10 Pro, Hyper-V may be enabled by hitting Win+S, searching for “Turn Windows features on or off”, ticking “Hyper-V” and rebooting your machine. Now you should be able to search for “Hyper-V Manager” to access all of your options. To quickly spin up a new VM, navigate to Action -> Quick Create… in the top bar.
From here, you can install any of the latest Ubuntu versions, including the most recent LTS version and any custom images you may have. Be sure to edit the VM settings afterwards and bump up the number of cores allocated to your VM (half is often a good balance). To start the VM, you can double click the entry which will also open a virtual display 🎉.
Note: to access the Internet from your VM, you will need to create an External Virtual Switch using Hyper-V. This can be done by selecting your physical machine under Hyper-V Manager, and finding the “Virtual Switch Manager” on the right-hand side of the screen. Then simply create an “External” switch and select the network adapter you’d like to share, e.g. your Wi-Fi card.
Now that your VM is up, we want to be able to access it without having to go through Hyper-V. This is best done using a secure shell (SSH), which you should now set up and enable on your fresh install. For Ubuntu, this can be done by installing openssh-server.
$ sudo apt update
$ sudo apt install openssh-server
$ sudo ufw allow ssh
While we’re at it, note down your VM’s hostname and your username, which we’ll need for the next step. We’ll refer to this as <your_hostname> and <your_username> respectively.
Now let’s set up Windows Terminal, a brand new terminal emulator built for Windows 10. First, we’ll need to set up our SSH targets. Hit Win+S, type “%USERPROFILE%” and hit enter. Create a new folder in your user folder called “.ssh” and inside create a new file called “config”. Give it the following format.
And finally, let’s link all of this together by configuring Windows Terminal to connect to your VM by default. Open Windows Terminal, hit Ctrl+, (comma) and give the opened file the following format.
Now, whenever you start Terminal, instead of seeing your Windows command shell, you should see a freshly installed Ubuntu shell instead!
Visual Studio Code
This is the step where it comes together. Now that you’ve configured your “%USERPROFILE%/.ssh/config” file as shown above, you can now access your VM directly from VS Code by using its Remote SSH plugin.
Once you’ve installed this plugin, press F1 and type “>Remote-SSH: Connect to Host…”. In the resulting list you should see “my-vm”. Select this and you should now be thrown into a VS Code window running inside of your VM!
Now you’ve got all of VS Code’s powerful tools at your disposal with the visual client running on Windows, but the back-end running in a Linux VM. This lets you use all of the tools available to *nix in a neatly contained environment.
Keep in mind the VM we’ve set up is a fully featured Linux machine, equivalent of one running natively on your machine. This comes with all of the customizability of *nix with the assurance that nothing you mess up will affect your main OS! I highly recommend exploring ways of making the environment work for you. A great start is the dotfiles rabbit-hole, and I’ve had great success running NixOS in this kind of environment.