WSL2: Making Windows 10 the perfect dev machine!
Tags: development, windows10, wsl2, ohmyzsh
Published: 2020-06-05 15:43:42

---
title: WSL2: Making Windows 10 the perfect dev machine!
date: 2020-06-05 15:28:59 UTC
tags: development,windows10,wsl2,ohmyzsh
canonical_url: http://partlycloudy.blog/2020/06/05/wsl2-making-windows-10-the-perfect-dev-machine/
published: true
cover_image: https://heartofcode.files.wordpress.com/2020/06/20200604_173617212_ios.jpg?w=1084
---

 **Disclaimer** : I work at Microsoft. And you might think that this makes me a bit biased about the current topic. However, I was an enthusiastic MacOS / MacBook user – both privately and professionally. I work as a so-called “Cloud Solution Architect” in the area of Open Source / Cloud Native Application Development – i.e. everything concerning container technologies, Kubernetes etc. This means that almost every tool you have to deal with is Unix based – or at least, it only works perfectly on that platform. That’s why I early moved to the Apple ecosystem, because it makes your (dev) life so much easier – although you get some _not so serious_ comments on it at work every now and then :)

Well, things have changed…

## Introduction

In this article I would like to describe how my current setup of tools / the environment looks like on my Windows 10 machine and how to setup the latest version of the Windows Subsystem for Linux 2 (WSL2) optimally – at least for me – when working in the “Cloud Native” domain.

Long story short…let’s start!

## Basics

### Windows Subsystem for Linux 2 (WSL2)

The whole story begins with the installation of WSL2, which is now available with the current version of Windows (Windows 10, version 2004, build 19041 or higher). The Linux subsystem has been around for quite a while now, but it has never been really usable – at least this is the case for version 1 (in terms of performance, compatibility etc.).

The bottom line is that WSL2 gives you the ability to run ELF64 Linux binaries on Windows – with 100% system call compatibility and “near-native” performance! The Linux kernel (optimized in size and performance for WSL2) is built by Microsoft from the latest stable branch based on the sources available on “kernel.org”. Updates of the kernel are provided via Windows Update.

I won’t go into the details of the installation process as you can simply get WSL2 by following this tutorial: [https://docs.microsoft.com/en-us/windows/wsl/install-win10](https://docs.microsoft.com/en-us/windows/wsl/install-win10)

It comes down to:

- installing the Subsystem for Linux
- enabling “Virtual Machine Platform”
- setting WSL2 as the default version

Next step is to install the distribution of your choice…

### Install Ubuntu 20.04

I decided to use Ubuntu 20.04 LTS, because I already know the distribution well and have used it for private purposes for some time – there are, of couse, others: Debian, openSUSE, Kali Linux etc. No matter which one you choose, the installation itself couldn’t be easier: all you have to do is open the Windows Store app, find the desired distribution and click “Install” (or simply click on this link for Ubuntu: [https://www.microsoft.com/store/apps/9n6svws3rx71](https://www.microsoft.com/store/apps/9n6svws3rx71)).

![](https://heartofcode.files.wordpress.com/2020/06/1-ubuntu_install.png?w=1024)<figcaption>Windows Store Ubuntu 20.04 LTS</figcaption>

![](https://heartofcode.files.wordpress.com/2020/06/2-ubuntu_install.png?w=1024)<figcaption>Ubuntu Installation</figcaption>

Once it is installed, you have to check if “version 2” of the subsystem for Linux is used (we have set “version 2” as default, but just in case…). Therefor, open a **Powershell** prompt and execute the following commands:

```powershell
C:\> wsl --list --verbose
 
  NAME                   STATE           VERSION
* Ubuntu-20.04           Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2
  Ubuntu-18.04           Stopped         2
```

If you see “Version 1” for Ubuntu-20.04, please run…

```powershell
C:\> wsl --set-version Ubuntu-20.04 2
```

This will convert the distribution to be able to run in WSL2 mode (grab yourself a coffee, the conversion takes some time ;)).

### Windows Terminal

Next, you need a modern, feature-rich and lightweight terminal. Fortunately, Microsoft also delivered on this: the [Open Source Windows Terminal](https://github.com/microsoft/terminal).  It includes many of the features most frequently requested by the Windows command-line community including support for tabs, rich text, globalization, configurability, theming & styling etc.

The installation is also done via the Windows Store: [https://www.microsoft.com/store/productId/9N0DX20HK701](https://www.microsoft.com/store/productId/9N0DX20HK701)

Once it’s on your machine, we can tweak the settings of the terminal to use Ubuntu 20.04 as the default terminal. Therefor, open Windows Terminal and hit “Ctrl+,” (that opens the settings.json file in your default text editor).

Add the _guid_ of the Ubuntu 20.04 profile to the “defaultProfile” property:

![](https://heartofcode.files.wordpress.com/2020/06/2-1-tweak-term.png?w=1024)<figcaption>Default Profile</figcaption>

Last but not least we upgrade all existing packages to be up to date.

```shell
$ sudo apt upgrade
```

So, the “basics” are in place now…we have a terminal that’s running Ubuntu Linux in Windows. Next, let’s give it super-powers!

## Setup / tweak the shell

The software that is now being installed is an extract of **what I need** for my daily work. Of course the selection differs from what you might want (although I think this will cover a lot someone in the “Cloud Native” space would install). Nevertheless, it was important for me to list almost everything here, because it basically also helps me if I have to set up the environment again in the future :)

### SSH Keys

Since it’s in the nature of a developer to work with GitHub (and other services, of course :)), I first need an SSH key to authenticate against the service. To do this, I create a new key (or copy an existing one to _~/.ssh/_), which I then publish to GitHub (via their website).

At the same time the key is added to _ssh-agent_, so you don’t have to enter the corresponding keyphrase all the time when using it.

```shell
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
 
# start the ssh-agent in the background
$ eval $(ssh-agent -s)
> Agent pid 59566
 
$ ssh-add ~/.ssh/id_rsa
```

### Oh My Zsh

![](https://heartofcode.files.wordpress.com/2020/06/omz.png?w=337)

Now comes the best part :) To give the Ubuntu shell (which is _bash_ by default) real superpowers, I exchange it with _[zsh](https://www.zsh.org/)_in combination with the awesome project _[Oh My Zsh](https://github.com/ohmyzsh/ohmyzsh)_ (which provides hundreds of plugins, customizing options, tweaks etc. for it). _zsh_ is an extended _bash_ shell which has many improvements and extensions compared to _bash_. Among other things, the shell can be themed, the command prompt adjusted, auto-completion can be used etc.

So, let’s install both:

```shell
$ sudo apt install git zsh -y
 
# After the installation has finished, add OhMyZsh...
 
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
```

When ready, _OhMyZsh_ can be customized via the _.zshrc_ file in you home directory (e.g. enable plugins, set the theme). Here are the settings I usually make:

- Adjust Theme
- Activate plugins

Let’s do this step by step…

#### Theme

As theme, I use _powerlevel10k_ (great stuff!), which you can find [here](https://github.com/romkatv/powerlevel10k).

![](https://heartofcode.files.wordpress.com/2020/06/performance.gif?w=884)<figcaption>Sample: <em>powerlevel10k</em> (Source: <a rel="noreferrer noopener" href="https://github.com/romkatv/powerlevel10k" target="_blank">https://github.com/romkatv/powerlevel10k</a>)</figcaption>

The installation is very easy by first cloning the repo to your local machine and then activating the theme in _~/.zshrc_ (variable _ZSH\_THEME_, see screenshot below):

```
$ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH\_CUSTOM:-~/.oh-my-zsh/custom}/themes/powerlevel10k
```

![](https://heartofcode.files.wordpress.com/2020/06/zsh_theme.png?w=1024)<figcaption>Adjust theme to use</figcaption>

The next time you open a new shell, a wizard guides you through all options of the theme and allows you to customize the look&feel of your terminal (if the wizard does not start automatically or you want to restart it, simply run `p10k configure` from the command prompt).

The wizard offers a lot of options. Just find the right setup for you, play around with it a bit and try out one or the other. My setup finally looks like this:

![](https://heartofcode.files.wordpress.com/2020/06/sample.png?w=1024)<figcaption>My <em>powerlevel10k </em>setup</figcaption>

**Optional, but recommended**...install the corresponding fonts (and adjust the _settings.json_ of Windows Terminal to use these, see image below): [https://github.com/romkatv/powerlevel10k#meslo-nerd-font-patched-for-powerlevel10k](https://github.com/romkatv/powerlevel10k#meslo-nerd-font-patched-for-powerlevel10k)

![](https://heartofcode.files.wordpress.com/2020/06/fonts.png?w=608)<figcaption>Window Terminal settings</figcaption>

### Plugins

In terms of OhMyZsh plugins, I use the following ones:

- **git** (_git_ shortcuts, e.g. “_gp_” for “_git pull_“, “_gc_” for “_git commit -v_“)
- **zsh-autosuggestions / zsh-completions** (command completion / suggestions)
- **kubectl** (_kubectl_ shortcuts / completion, e.g. “_kaf_” for “_kubectl apply -f_“, “_kgp_” for “_kubectl get pods_“, “_kgd_” for “_kubectl get deployment_” etc.)
- **ssh-agent** (starts the ssh agent automatically on startup)

You can simply add them by modifying _.zshrc_ in your home directory:

![](https://heartofcode.files.wordpress.com/2020/06/zsh_plugins.png?w=1024)<figcaption>Activate oh-my-zsh plugins in <em>.zshrc</em></figcaption>

## Additional Tools

Now comes the setup of the tools that I need and use every day. I will not go into detail about all of them here, because most of them are well known or the installation is incredibly easy. The ones, that don’t need much explanation are:

- **Azure CLI** (`curl -sL https://aka.ms/InstallAzureCLIDeb | sudo zsh`) + **kubectl** (handy installer via Azure CLI: _`az aks install-cli`_)
- **Node Version Manager NVM** (`wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | zsh`) and **NodeJS LTS** version (current: nvm install v12.18.0)
- **Azure Functions Core Tools** (npm install -g azure-functions-core-tools@3)
- **Terraform** ([https://www.terraform.io/downloads.html](https://www.terraform.io/downloads.html))
- **Helm** via _get\_helm.sh_ script(`curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3`)
- **Go** (`sudo apt install golang`)
- **.NET Core** (simply follow [https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-manager-ubuntu-2004](https://docs.microsoft.com/en-us/dotnet/core/install/linux-package-manager-ubuntu-2004))
- **jq** – work with JSON data in the shell ([https://stedolan.github.io/jq/download/](https://stedolan.github.io/jq/download/))

## Give me more…!

There are a few tools that I would like to discuss in more detail, as they are not necessarily widely used and known. These are mainly tools that are used when working with Kubernetes/Docker. This is exactly the area where _kubectx/kubens_ and _stern_ are located. _Docker for Windows_ and _Visual Studio Code_ are certainly well known to everyone and are familiar through daily work. The reason why I want to talk about the latter two is because they meanwhile tightly integrate with WSL2!

### kubectx / kubens

Who doesn’t know it? You work with Kubernetes and have to switch between clusters and/or namespaces all the time…forgetting the appropriate commands to set the context correctly and typing yourself “to death”. This is where the tools _kubectx_ and _kubens_ come in and help you to switch between different clusters and namespaces quickly and easily. I never want to work with a system again where these tools are not installed – honestly. To see _kubectx_/_kubens_ in action, here are the samples from their [GitHub](https://github.com/ahmetb/kubectx)repo:

![](https://heartofcode.files.wordpress.com/2020/06/kubectx-demo.gif?w=1024)<figcaption><em>kubectx </em>in action</figcaption>

![](https://heartofcode.files.wordpress.com/2020/06/kubens-demo.gif?w=1024)<figcaption><em>kubens </em>in action</figcaption>

To install both tools, follow these steps:

```
$ sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx$ sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx$ sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubensmkdir -p ~/.oh-my-zsh/completionschmod -R 755 ~/.oh-my-zsh/completionsln -s /opt/kubectx/completion/kubectx.zsh ~/.oh-my-zsh/completions/\_kubectx.zshln -s /opt/kubectx/completion/kubens.zsh ~/.oh-my-zsh/completions/\_kubens.zsh
```

To be able to work with the autocomletion features of these tools, you need to add the following line at the end of your _.zshrc_:

```
autoload -U compinit && compinit
```

Congrats, productivity gain: 100% :)

### stern

_[stern](https://github.com/wercker/stern)_allows you to output the logs of multiple Pods simultaneously to the local command line. In Kubernetes it is normal to have many services running at the same time that communicate with each other. It is sometimes difficult to follow a call through the cluster. With stern, this becomes relatively easy, because you can select pods by e.g. label selectors from which you want to follow the logs.

With the command `stern -l application=scmcontacts` e.g. you can stream the logs of all pods with the label _application=scmcontacts_ to your local shell…which then looks like that (each color represents another pod!):

![](https://heartofcode.files.wordpress.com/2020/06/image.png?w=1024)<figcaption>stern log streams</figcaption>

To install stern, use this script:s

```shell
$ sudo curl -fsSL -o /usr/local/bin/stern https://github.com/wercker/stern/releases/download/1.11.0/stern\_linux\_amd64
$ sudo chmod 755 /usr/local/bin/stern
```

### One more thing

**Docker for Windows** has been around for a long time and is probably running on your machine right now. What some people may not know is that Docker for Windows integrates seamlessly with WSL2. If you are already running Docker on Windows, a simple invocation of the settings is enough to enable Docker / WSL2 integration:

![](https://heartofcode.files.wordpress.com/2020/06/dockerwsl.png?w=1024)<figcaption>Activate WSL2 based engine</figcaption>

![](https://heartofcode.files.wordpress.com/2020/06/docker_wsl2.png?w=1024)<figcaption>Choose WSL / distro integration</figcaption>

If you want more details about the integration, please visit this page: [https://www.docker.com/blog/new-docker-desktop-wsl2-backend/](https://www.docker.com/blog/new-docker-desktop-wsl2-backend/) For this article, the fact that Docker now runs within WSL2 is sufficient  :)

Last but not least, one short note. Of course, **Visual Studio Code** can also be integrated into WSL2. If you [install a current version](https://code.visualstudio.com/download) of the editor in Windows, all components to run VS Code with WSL2 are included.

A simple call of `code .` in the respective directory with your source code is sufficient to install the Visual Studio Code Server ([https://github.com/cdr/code-server](https://github.com/cdr/code-server)) in Ubuntu. This allows **VSCode** to connect remotely to your distro and work with source code / Frameworks that are located in WSL2.

That’s all :)

## Wrap-Up

Pretty long blog post now, I know…but it contains all the tools that are necessary (take that with a “grain of salt” ;)) to make your Windows 10 machine a “wonderful experience” for you as a developer or architect in the “Cloud Native” space. You have a full compatible Linux “system”, which tightly integrates with Windows. You have .NET Core, Go, NodeJS, tools to work in the “Kubernetes universe”, the best code editor currently out there, git, ssh-agent etc. etc.…and a beautiful terminal which makes working with it simply fun!

For sure, there are thing that I missed or I just don’t know at the moment. I would love to hear from you, if I forgot “the one” tool to mention. Looking forward to read your comments/suggestions!

Hope this helps someone out there! Take care…

Photo by [Maxim Selyuk](https://unsplash.com/@artplay?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/@artplay?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)