DEV Community

Scott Coulton for Microsoft Azure

Posted on • Originally published at Medium

Windows for a Linux guy

I recently moved to Microsoft for work and got a choice of laptop. I decided to go down the Surfacebook route as a change is as good as a holiday and I had a Dell xps prior. Being a Linux guy (Debian the OS of choice) the first thing I did was dual boot it. Got everything up and running with no issues which was awesome. Then I started to look at WSL and I noticed there was a Debian stretch install. I got to wondering how close could I get this to my native Linux setup?

To give you the context of my Linux setup, I run i3wm, I run vscode for golang development, I still love vim for everything else, golang as mentioned, azure cli, docker, minikube and last but not least my git bash prompt. If I got all this working I would be pretty happy. As this is going to be a long post I am not going to go through installing git etc as you just use apt-get for that.

Before we start there is a disclaimer. As mentioned I am not a Windows expert. So if you are a Windows expert and are reading this and you see something wrong or could be done better. Just hit me up on Twitter and I will update the post and give you credit on the post for your help.

If you are new to WSL read the docs here it will get you started. As mentioned before I am using Debian but I am assuming this setup will work with Ubuntu as well.

Now let’s start. The first thing on my list was i3wm, the reason I love i3 is its all keyboard based and super efficient when using a terminal. Now I found you can get this working on WSL by installing a x server and forwarding it to a client on the Windows side. I found this to be a little heavy-handed for what I needed so I decided to go with tmux as all I really needed was to be able to manipulate the terminal panes. I found a really good package manager for tmux that allows you to get some really cool features without having a massive .tmux.conf You can find the list of plugins available here. My .tmux.conf looks like this

# list of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-online-status'
set -g @plugin 'tmux-plugins/tmux-yank'
set -g @plugin 'tmux-plugins/tmux-pain-control'

# status bar
set -g status-bg red
set -g status-fg white
​
# online check
set -g status-right "Online: #{online_status} | %a %h-%d %H:%M "
​
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run -b '~/.tmux/plugins/tpm/tpm'
​
# mouse stuff
set -g mouse on
set-window-option -g mouse on

As you can see its really short and gives me the power to manipulate the terminal panes and I have copy and paste with vim keys. Winning! Except you will notice at the right-hand side of the online status that the tick is not showing. This is because the default font consolas does not have the characters we need. So we will need to install a new font, I chose to use DejaVu Sans Mono So all you need to do is download and install the font on the Windows OS then right click WSL top bar, select Defaults, the Font and change the font of the terminal to use DejaVa Sans Mono. Then the problem is fixed and the terminal also now looks more like a native Linux terminal. If you want tmux to start automatically when WSL opens add this to your .bashrc

if [ "$TMUX" = ""]; then tmux -u; fi

Next cab off the rank will be Docker. Now you can get Docker running natively inside WSL . To accomplish that we will need to do only a few things. Firstly, install Docker for windows (instructions here) While we are in the WSL terminal we will need to add the following to our .bashrc

alias docker='docker.exe'

Now if we go back to the WSL terminal and enter docker ps it should be all working. If not make sure you source .bashrc What we have done here is alias the docker.exe binary to docker This will make the setup feel more like a native Linux install of Docker. This has been updated from my original post where we forwarded the Docker daemon over a non-encrypted tcp port. This new way is more secure.

Next in line is the Azure cli, that is pretty straightforward follow the instructions here for Debian. Then run az login from the terminal to get you up and running.

We will then install kubectl in the Debian terminal with the following instructions.

The next tool is something I have only found recently but it is so useful it is kubectx If you have not used it before I would recommend that you check it out and for a quick rundown it basically a tool for managing your Kubernetes clusters credentials in ~/.kube/config file. To install go to the Github page here and follow the installation method for bash. We will park this for now but come back to it later as well will use kubectx in our bash functions to make everything seamless to run.

The last easy piece of the puzzle was was the bash git prompt. I like this one https://github.com/magicmonty/bash-git-prompt and it's a personal choice but now we have our new font installed everything will work.

Vim is also an easy one to install with sudo apt-get install vim I like to add a few tweaks and install pathogen and nerdtree. Then we will get something like the below image.

Now we will move onto the more challenging apps to get working firstly we will tackle minikube. Now to install minikube and get it working on Windows is not difficult, to access it from WSL is also not difficult. I have a workflow that allows me to spin up clusters on Azure or minikube with a single command. I wanted to replicate that workflow. So the two biggest hurdles to getting this working are you have two installations of kubectl one on the Windows OS and the other on the Debian side. The second is minikube needs to start with admin privileges due to using hyper-v. So let’s run through the solution.

The first thing I did was create a default switch in hyper-v called minikube. this can be done in the hyper-v manager and click on the virtual switch manager Then create a new switch called minikube that is an external switch.

To install minikube follow the instructions here using chocolatey. Now we have all the plumbing in place. We need to then open WSL as an administrator otherwise as mentioned earlier we cant execute hyper-v commands. So to do this I just right on the WSL icon and use the run as adminstrator (i know I need to find a better way to do this) Now let's add some bash aliases. Calling a binary with a .exe at the end does not feel natural in Linux so the first bash alias will just alias the minikube.exe binary with minikube like so alias minikube='minikube.exe This is for when you are manually typing commands in the terminal. The next is you probably want bash autocompletion as its super handy. Add this to your .bashrc
source <(minikube.exe completion bash)>

Ok now lets alias creating our minikube node. I have created a file called ~/.kubefunc and I source it from my ~/.bash_profile Its a personal choice but I think it keeps things tidy and easy to update. Here is the code to run the cluster.


#!/bin/bash
minikube_docker () {
minikube.exe start --memory=8192 --cpus=4 \
  --vm-driver=hyperv \
  --hyperv-virtual-switch=minikube \
  --kubernetes-version=v1.13.0 \
  --bootstrapper=kubeadm \
  --extra-config=apiserver.enable-admission-plugins="LimitRanger,NamespaceExists,NamespaceLifecycle,ResourceQuota,ServiceAccount,DefaultStorageClass,MutatingAdmissionWebhook"
kubectl config set-cluster minikube --server=https://$(minikube.exe ip):8443 --certificate-authority=/mnt/c/Users/sccoulto/.minikube/ca.crt
kubectl config set-context minikube --cluster=minikube --user=minikube
kubectl config set-credentials minikube --client-certificate=/mnt/c/Users/sccoulto/.minikube/client.crt --client-key=/mnt/c/Users/sccoulto/.minikube/client.key
kubectx minikube

Now let's break it down. So the function is called minikube_docker ( I have a containerd one as well) We start the server with cpu and memory, use hyper-v as the vm driver, reference the hyper-v switch we created earlier, chose the kubernetes version, use kubeadm to bootstrap the cluster, the next bit is extra config that I pass to the kubelet to be able to test other application on Kubernetes like istio or knative. The last four lines I am getting the cluster credentials from inside the Windows OS and passing them to the local WSL kubectl and then setting the current context to use minkube with kubectx Now we are set to spin up our cluster. So as I mentioned earlier I source the .kubefunc file from my .bash_profile so for me its source ~/.bash_profile Then run minikube_docker wait a few minutes and you will have a working cluster. To test this just run kubectl get nodes from inside WSL. Don't forget if copied and pasted the code from above to change sccoulto to your username. One last thing we need to do as a cleanup task is to create another function to delete the cluster and clear it off both our kubectl configs.

minikube_delete () {
minikube delete
kubectx -d minikube
}

minikube delete will clean up the Windows OS side and kubectx -d minikube cleans up our WSL Debian OS.

Now we have covered a lot and the end is in sight the last thing to cover is setting up our Go environment. So to be able to use vscode we will install it on Windows as per normal. Then we are going to install go onto the windows OS as per the instructions here but we are going to change a few things like the GOPATH this is so we have it in a place that we can access it from both the Windows OS and WSL. I created it in my home directory Documents\Development\go but you can use anywhere in your home directory. We need to add the environment variables to the Windows os under user variables. One for GOPATH and then point it to the go folder you just created. Then add the bin directory from inside the new go folder to the path.

Then we install go on WSL just following the normal Linux instructions here. We will then add the following to our ~/.bash_profile

# golang
export GOROOT=/usr/local/go
export GOBIN=/mnt/c/Users/sccoulto/Documents/Development/go/bin
export GOPATH=/mnt/c/Users/sccoulto/Documents/Development/go
export PATH="$PATH:/usr/local/go/bin:/mnt/c/Users/sccoulto/Documents/Development/go/bin"

Now we are pointing both installations at the same folders. Now for our last setting in vscode. I want to use the WSL terminal in vscode so I need to change the default terminal under user settings to bash.exe

Now we are done, so I think we have got really close to a native Linux feel on Windows. There are a few bumps that you will encounter on the way and it is a little bit slower than native Linux. But if you are a Windows engineer wanting to learn Linux or a Linux guy with a Windows laptop this is a very solid solution. As for the surface book after two weeks I am happy with it, the keyboard and screen are amazing.

Just a final word, a big shout out to all that work on the WSL project. Really awesome work !!! Also to all the other opensource developers mentioned in this post. Your hard work is greatly appreciated

Top comments (0)