WSL2 Setup For Distributing To IaC Developers — Ansible Focus


There are some basics first on setting WSL2 — Windows Subsystem for Linux Version 2 on your windows machine. I will not go too in depth but just share links I leveraged for setting up my own machine for WSL2. Prerequisite is that you have administrator rights to your windows machine. This can be an issue in work environments. For this work we will leverage Ubuntu 20.04 for our Linux OS.

What I will cover in this story:

  1. Installing WSL2 On Windows
  2. Getting your first WSL2 image installed
  3. WSL Basic Commands — Import/Export/etc.
  4. Some networking issues to watch out for
  5. Initial WSL Setup including ansible
  6. Installing podman, ansible-navigator, ansible-builder, ansible-lint leveraging ansible
  7. IaC Developer Start Guide
  8. Visual Studio Code — Remote Development WSL

The hope from this is you have more understanding of the power of WSL and how your team, organization, or community could benefit from leveraging this setup.

Installing WSL2 On Windows

As mentioned in overview, I won’t get into depth here but hopefully provide enough guidance to those that need it. However, this guide will step through grabbing your first distribution a different way then leveraging Microsoft Store as application and does add few more things than is necessary. So, you can skip the install distribution of your choice for following this guide but not issue if you do want to install as mentioned either. Distribution installation is discussed in the next section.

Prior to installing WSL you will want to have BIOS setting updated for virtualization and Hyper-V feature enabled. You may want to ensure BIOS first.

BIOS Help:

Enable Hyper-V — Microsoft Docs

Microsoft has a pretty good installation guide to follow:

Install WSL — Microsoft Docs

However, it does forget to mention requirement for Hyper-V to be installed and BIOS setting for virtualization.

It does mention the build number to watch out for. From command prompt you can check your version with the winver command:

I had to follow the older instructions found here:

Manual Installation Steps for older versions of WSL — Microsoft Docs

Ubuntu also has a WSL installation guide

Getting your first WSL2 image installed

You can skip this portion if you already installed the Ubuntu WSL Distribution from the Microsoft Store.

First we need to grab the image to leverage our first WSL environment. There are few different ways to get a base image.

This will download Ubuntu’s WSL Microsoft Store Image by using the Command Prompt as an Administrator: (Replace Administrator with your username when setting environment variable)

curl.exe -L -o ubuntu-2004.appx Rename to zip extension
Rename-Item .\ubuntu-2004.appx .\
# Expand zip file
Expand-Archive .\\Ubuntu
# Enter Ubuntu Directory
cd .\Ubuntu\
# Get proper appx
Rename-Item Ubuntu_2004.2021.825.0_x64.appx
# Expand proper distribution
Expand-Archive .\ .\Ubuntu
# Enter Another Ubuntu Directory
cd .\Ubuntu\
#Add your Linux distribution path to the Windows environment PATH
#(C:\Users\Administrator\Ubuntu in this example)
$userenv = [System.Environment]::GetEnvironmentVariable("Path", "User")
[System.Environment]::SetEnvironmentVariable("PATH", $userenv + ";C:\Users\Administrator\Ubuntu", "User")
# Now we run the executable which will load the first distribution
# Now exit the terminal and export so we have a base WSL image
# Export WSL Distribution To New Image
wsl --export Ubuntu Ubuntu.tar
# Compress WSL Image
wsl.exe gzip Ubuntu.tar

Ubuntu points to . However, I don’t see any WSL images as of writing this story and did reach out to them. I did find WSL images posted here

Reference Documentation for install:

WSL Basic Commands — Import/Export/etc.

Here are some basic commands when working with WSL.

  • Set Default WSL Version for new imports (WSL2 gives large performance improvements)
wsl --set-default-version 2
  • Import an image:
wsl --import [NameYouWantToGiveToEnv] .\[NameYouWantToGiveToEnv] [filepath]\[filename_of_wsl_image]
  • Export an image and then compress (not done by default):
wsl --export DistributionName SomeNameOfFile.tar
wsl.exe gzip SomeNameOfFile.tar
  • Stop Particular Instance
wsl --terminate DistributionName
  • Stop All Instances
wsl --shutdown
  • Remove and delete hard drive of WSL instance
wsl --unregister DistributionName

Networking Pitfalls To Watch Out For

Now that you have a distribution up and running, I want to mention networking pitfalls. This is where a lot of people struggle with setting up their WSL environment. This will less likely to be an issue on a personal machine and more likely to be in corporate environment.

First off there is the /etc/resolv.conf file that is used for nameservers. In corporate environment you may need to reach out to a Linux systems administrator if you don’t know what the proper settings are for the resolv.conf file. A way to fix that is to add google as your nameserver. Depending on your own system as well that could be an issue because sometimes /etc/resolv.conf is turned into a symbolic link. At this point I’m still expecting that your are logged in as root.

if [[ -L "/etc/resolv.conf" ]]; then
rm "/etc/resolv.conf"
echo 'nameserver' > /etc/resolv.conf

However, WSL has an autogenerate policy by default to the /etc/resolv.conf file via the /etc/wsl.conf that you will need to also update:

echo '[network]' > /etc/wsl.conf
echo 'generateResolvConf = false' >> /etc/wsl.conf

For more information on the wsl.conf file you can go to Microsoft’s documentation:

Those really are the two biggest pitfalls for networking. However, some more subtle ones I know about are these:

  • VPN — Breaks Interface Metric

This one was one of the most tricky network issues I faced that took some homework. Issue is every time you connect to VPN it sets its interface metric to one break WSL connectivity outside your local machine.

Credit goes to this post:

From PowerShell on local machine this was required every time connected to VPN: (Note: Be careful on the name of vpn you can use wildcard I just didn’t as want to ensure you don’t change other settings on accident.)

Get-NetAdapter | Where-Object {$_.InterfaceDescription -Like "NameOfVpnGoesHere"} | Set-NetIPInterface -InterfaceMetric 4000Get-NetIPInterface -InterfaceAlias "vEthernet (WSL)" | Set-NetIPInterface -InterfaceMetric 1

To validate proper setting for VPN you can leverage something like this:

Get-NetAdapter | Where-Object {$_.InterfaceDescription -Like "NameOfVpnGoesHere*"} | Get-NetIPInterface
  • Certificates in Enterprise Environment

For certificate related issue; again you may need help from a systems administrator getting the certificates. However, part of my initialize script contains the following:

# Install Proper Certificates
cd /usr/local/share/ca-certificates/school
sudo update-ca-certificates

Initial WSL Setup including ansible

So, hopefully by now you have WSL v2 installed and an image we can leverage. You maybe ahead here but will take consideration that you have image without it installed/imported.

Let’s leverage the image and perform import command which were shown earlier then enter that version. Images you import won’t be altered and great way to roll back changes and do testing with the import export. Decide where you want the folder structure to be on your machine.

wsl -l -v
wsl --set-default-version 2
wsl --import UbuntuBase .\UbuntuBase C:\wsl\images\Ubuntu-20.04.tar.gz
wsl -d UbuntuBase

** STOP HERE if following steps as a IaC Developer from below section **

Now that we are in a base Ubuntu image; here is a startup script I leverage (again this is if creating a distribution image from others leveraging base WSL distribution image):

if (( $EUID != 0 )); then
echo 'Run script as root'
echo 'Ensure /etc/resolv.conf isnt symlink'
if [[ -L "/etc/resolv.conf" ]]; then
echo 'Removing symlink file: /etc/resolv.conf'
sudo rm "/etc/resolv.conf"
echo 'Removed symlink file: /etc/resolv.conf'
# Fix network issues as first step and this would need to be done manually since wont have connectivity out of WSL
# May need to add your own nameservers and setup to resolv.conf
echo 'nameserver' > /etc/resolv.conf
echo '[network]' > /etc/wsl.conf
echo 'generateResolvConf = false' >> /etc/wsl.conf
# Install Proper Certificates
cd /usr/local/share/ca-certificates/
mkdir school
cd school
sudo update-ca-certificates
# Install Ansible To Leverage That For Rest of Setup Work
apt-get update
apt install python3-pip -y
pip install ansible

Now to leverage this script perform the following:

cd /
# COPY and PASTE via vi editor script above
# Would pull from somewhere but this does have a network fix in it
# You may run into issue if that was case so just having it combined
chmod 775

Now that script is complete you have a working setup with ansible installed.

Feel free to have this exported as an image for leverage later if desired.

Installing podman, ansible-navigator, ansible-builder, ansible-lint leveraging ansible

The next step is really about then leveraging ansible to do the rest of the setup work. I create a WSL image after the initial setup with export to leverage as one of my base images for testing that just has networking and ansible. After the next step that is my base image that is distributed for others to leverage for their own WSL development without the need for all of this work and understanding that is going on; hopefully. Just to give them an environment that they can then start doing their development on. Of course, it is great for them to also understand this if they have time.

Main code for standing up rest of the environment is done by ansible and hosted on github; you can look through the code there to understand what is happening:

cd /
git clone
cd /wsl_ubuntu_image_setup
ansible-playbook init.yml

Now, pending that all those steps worked. You have an environment setup with ansible already installed from before. However, now also setup in the WSL environment are the following:

  • New user iacdev created
  • podman
  • ansible-navigator (for iacdev user)
  • ansible-builder
  • VS Code Suggested Ansible plugin recommendation (more later)

So, now we have all the basic standup work is done and ready to export the image for distribution to developers. The next sections will be showing how to leverage that from the developers point of view that hasn’t been involved until now. You can give the distribution image any name you want. You will want to run the gzip afterwards to get a compressed image to share out.

wsl --export UbuntuBase distribution_name.tar
wsl.exe gzip distribution_name.tar

IaC Developer Start Guide

So, the prior sections of this story was showing getting a WSL image setup for distribution to you — the IaC Developer. However, some of the same steps will apply. I recommend that you read the other parts but it is a quick read. You will need to have WSL 2 installed on your machine. Following steps above are the same but now you can leverage the distributed image given to you from the work done above that was done for the setup for your team, company, etc.

Once WSL 2 is installed, you can follow the section “Initial WSL Setup including ansible” and import that image as mentioned above. You can give your distribution a different name than UbuntuIaC if you want.

wsl -l -v
wsl --set-default-version 2
wsl --import UbuntuIaC .\UbuntuIaC distribution_name.tar.gz
wsl -d UbuntuIaC

We are now in our WSL environment for the first time. Now for easy development from here I recommend Visual Studio Code. However, you now have a WSL 2 environment you can do local development and testing with that has network connectivity.

If you have network issues I recommend you read that section as well, particularly at this point the section mentioned as PowerShell commands as you should have a well working WSL network side environment already provided to you.

Some other first time important items to remember:

# Perhaps a script be provided for the things required 
# for your team/company
# Working with git
git config --global "Your Name"
git config --global
# Working With Galaxy Tokens; best use environment variables
# Avoid Tokens from showing up into source control

Visual Studio Code — Remote Development WSL

First download and install Visual Studio Code if you haven’t already:

For the Ansible extension it is best to switch the Color Theme. I give a preference but plenty out there just I’d recommend testing to see how it works with the ansible highlighting of code as they do make a difference.

After Visual Studio Code is installed; to connect to the WSL environment we need to install Microsoft’s Remote Development Extension:

Now that we have Visual Studio Code installed with Remote Development Extension; we can launch a VS Code instance from our WSL terminal.

From directory you want to be connected to; run the command code .

However, if you get an issue running the command something like this could fix it as it’s probably issue with $PATH variable in some way. Most likely this part is missing from your $PATH variable:

export PATH="$PATH:/mnt/c/Users/[your_username_here]/AppData/Local/Programs/Microsoft VS Code/bin"

You can also add it to more permanently to your windows environment variables:

The way the above works is actual the code command is running from your own machine through the WSL.

Now WSL will be connected in VS Code Workspace that is loaded up:

Trust the authors and you are pretty much ready to go. Since some of my setup included creating extensions.json in .vscode folder loaded this happens:

Install the extension which actually loads into the WSL environment.

extensions.json for reference:

"recommendations": [

For reference on the extension itself:

However, even though I have settings.json configured it needs to be updated to actual run extension properly. Just updating save time on file will make it work or you can relaunch VS Code again running the code . command from the Ubuntu terminal. I do recommend reading the Ansible extension on marketplace if you are doing ansible development.

You can also leverage terminal within VS Code to interact with the WSL

If you don’t set the Run Ansible option on your yml or yaml files you need to ensure you have your extensions set in settings.json under .vscode:

"files.associations": {
"**/*.yml": "ansible",
"**/*.yaml": "ansible"

However, you may need to close VS Code after this and rerun the code . command to get the Ansible Extension for VS Code working properly. Another option is to remove the 2 associations and save the file and add them back and then they should be picked up.

Image from Red Hat extension page showing color highlighting

Future topics:

  • ansible-builder execution environments
  • ansible-navigator configuration
  • ansible-lint configuration
  • ansible-galaxy and token management to avoid in source control
  • podman with local registry for testing ansible execution environment images



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Matthew D Clark

Matthew D Clark

Director, DevOps Coach at Sun Life. The views and opinions expressed here are my personal opinions, and do not necessarily reflect official policies of Sun Life