9 minute read

Windows 10 + Vagrant + WSL2 + Ansible

So, wether you are setting your homelab up for learning purposes, or your homeserver if you have the more advanced knowledge, or even on production in a company, you may want to automatize the process of creating, configuring and deleting Virtual Machines (VM’s) for multiple purposes.

What is Vagrant?

You may use any of the most popular virtualization software out there like VirtualBox, VMware, Hyper-V, KVM, AWS, Docker, etc… but creating Virtual Machines the manual way can be a hustle and bustle as it usually requires to download an ISO File for the target OS that you are going to install into and then wait for the installation process which can take a while to complete. Once you have one Virtual Machine up and working most of these software programs allo you to replicate the configuration so that you can create multiple other machines in a matter of seconds.

But what if you could have a Virtual Machine up and running with all the configurations needed already done in just a matter of seconds? And not only that, but allows you to move that virtual machine to another computer by just sending a text file. That is Vagrant, a software that allows creation and management of portable virtual machines.

So how does Vagrant work? Vagrant uses “Provisioners” and “Providers” as building blocks to manage the development environments. Provisioners are tools that allow users to customize the configuration of virtual environments. Examples of the most used Provisioners used in Vagrant are Puppet and Ansible, being the latter the one we are covering in this post later on. Providers are the services that Vagrant uses to set up and create virtual environments. Vagrant comes with native support of VirtualBox, Hyper-V, and Docker virtualization, while VMware and AWS are supported via plugins.

What we are covering in this post is using Vagrant and Ansible in Windows 10 using Windows Subsystem for Linux in it’s second version (WSL2). This newer version of WSL launches a full virtual machine of Linux (in the Windows Store you can choose to install Ubuntu, Debian, Kali, Suse, etc…), so since it is a full Linux OS that is running everything should work just like in a Linux partition right? Well, not quite… WSL2 directories runs on it’s own network adapter usually called vEthernet (WSL), so accesing resources from either side (Windows 10 to WSL2 filesystem and folders as well as from WSL2 to Windows 10 filesystem and folders) makes use of the ethernet adapter all the time, and everything goes through the firewall and here is when things get complicated when you try to set things up for the first time (not anymore since I am giving all the steps needed to circumvent all the probles that may arise during installation and first use of Vagrant).

Installation

Now, let’s get our hands dirty doing what we love the most: the terminal. For Vagrant to work with WSL2 and Windows 10 we need to install the same version of Vagrant in both Windows 10 and WSL2.
For The Windows installation you may go to the downloads page of Vagrant and download the binary for the OS version you are using 32-bit or 64-bit. Nowadays is more likely that you are using the 64-bit, but if you are not sure what you are using type uname -i in the WSL terminal and it will print what OS you are using.
Once it is donwloaded and installed open your WSL terminal and, assuming you are using Debian or a Debian derived OS like Ubuntu, type the following commands:

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vagrant

In the downloads page you may find the commads needed for yum, dnf o brew if you are using CentOS/RHEL, Fedora or Homebrew respectively.

Image: Other installation methods.

Once installation finishes make sure that the installed version matches with the one in Windows 10 (at the time of writing this article the last version of Vagrant is 2.2.19):

$ vagrant --version
Vagrant 2.2.19

Now we can install VirtualBox (if not already installed) or update it to the latest version which at the time of writing this article it is version 6.1. You should take note of the installation directory because it will be needed later on (default is “C:\Program Files\Oracle\VirtualBox”).

Configuration

Next thing we need is to enable the access of Vagrant to the Windows 10 installation of your Provider, in our case we will use the default one (and most supported by Vagrant) which is VirtualBox. This is done by exporting a couple of variables in the WSL2 terminal.
The first variable VAGRANT_WSL_ENABLE_WINDOWS_ACCESS will enable the use of an external provider instead of using a VirtualBox installed inside WSL2 and will use therefore the one installed in the host OS.
The second variable will be adding the VirtualBox install folder location to the PATH of the WSL2 user. So in order to export these variables you could edit the file ~/.bashrc with your favourite text editor or add them to the end of the file with these commands and then restart the shell (logout and login works):

echo 'export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"' >> ~/.bashrc
echo 'export PATH="$PATH:/mnt/c/Program Files/Oracle/VirtualBox"' >> ~/.bashrc

As I mentioned before I’m using the default install location, you may need to adjust the command with your own path to VirtualBox location.

We are not done just yet, but we are getting there to launch our first Virtual Machine and connecting through ssh to it. If you try to launch a Virtual Machine with Vagrant you will be met with errors that can look like these:

default: Warning: Connection refused. Retrying...
default: Warning: Connection refused. Retrying...
default: Warning: Connection refused. Retrying...
default: Warning: Connection refused. Retrying...
default: Warning: Connection refused. Retrying...
default: Warning: Connection refused. Retrying...

To fix this, the community has created a plugin. You can find the source code here, thanks Karandash8. To install it just run:

vagrant plugin install virtualbox_WSL2

At this point you could launch a Vagrant VM but the process would get stuck at default: SSH auth method: private key:

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'centos/7' version '2004.01' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 172.25.64.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key

To fix this we need to disable the firewall of the vEthernet (WSL) interface. To do that we will open the Windows Firewall either searching for firewall on Windows 10 Start Menu or typing:

wf.msc

You will have to disable vEthernet (WSL) for the three profiles domain, private and public as shown in the pictures below:

Go to firewall properties
For each of the three profiles click on customize
Untick vEthernet (WSL)

You may have to follow these steps every time you reboot your computer as in my case Windows 10 seems to reset that config.

Last steps

The last thing you should do fixes a problem that could happen to you when creating and running multiple VMs with ansible, if you ever come across this message:

Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter'

Apparently it is easy to fix as pointed out here:

  1. Open Windows Network Connections.
  2. Right click on VirtualBox Host only adapter.
  3. Choose properties.
  4. Check “VirtualBox NDIS6 Bridged Networking driver”.
  5. Disable and Enable the adapter.
Checking and uncheking this option and disabling and enabling the adapter seems to fix the problem.

There are other fixes that than be tried if none of the above does the trick, you can read more about them here.

Running Vagrant with Ansible

Yes! You made it here! You can finally launch your first Virtual Machine. First go to Discover Vagrant Boxes and choose the image that you wish. For this example I will choose centos/7.

Create a folder for the project, cd to it and run:

vagrant init centos/7

This command will create a Vagrantfile that you will need to edit to match your preferences. In this example the first thing we are going to do is to disable the shared folders option that Vagrant has activated by default for every VM that you create, so for every Vagrantfile you will have to disable it by adding this line config.vm.synced_folder ".", "/vagrant", disabled: true:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "centos/7"
  config.vm.synced_folder ".", "/vagrant", disabled: true
  
end

Otherwise it will give an error, and we don’t need the shared folder just now.

At this point you could type vagrant up, Vagrant will download the image and run it automatically. Once booted you can type vagrant ssh to ssh into it.

Adding Ansible support is rather easy, the Vagrantfile should look like this once we remove all the text clutter:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "centos/7"
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
  end
end

You can now create a playbook.yml file in the same directory to play with the machine. I will paste the example I followed that user Geerlingguy created in his Ansible 101 series of videos:

---
- hosts: all
  become: yes
  tasks:
    - name: Ensure NTP is installed
      yum:
        name: ntp
        state: present
    - name: Ensure NTP is running
      service:
        name: ntpd
        state: started
        enabled: yes

This will check wether the NTP service is installed or not and if it is running or not. If you have your machine already up and running you can apply the playbook with the following command:

vagrant provision

A normal output would look like this:

$ vagrant provision
==> default: Running provisioner: ansible...
    default: Running ansible-playbook...

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [default]

TASK [Ensure NTP is installed] *************************************************

ok: [default]

TASK [Ensure NTP is running] ***************************************************
changed: [default]

PLAY RECAP *********************************************************************
default                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

You can see a changed=1 in the text, that means NTP service was not running. If we run the same command again we should see changed=0:

$ vagrant provision
==> default: Running provisioner: ansible...
    default: Running ansible-playbook...


PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************

ok: [default]


TASK [Ensure NTP is installed] *************************************************
ok: [default]


TASK [Ensure NTP is running] ***************************************************

ok: [default]

PLAY RECAP *********************************************************************
default                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Wrapping up

As you can see using Vagrant with WSL2 on Windows 10 is not quite as straightforward as it would be in a Linux computer or a Linux partition, but heck if it is supposed to work why not try to make it work? For me it took some good Googling around trying everything that users mentioned, it was a lot of reading, but in this post I think I have summarized very well what it needs to make it work. At least with Vagrant version 2.2.19, who knows if a future update breaks everything, but so far I’m not thinking of updating it.

If it works, don’t touch it


Information taken from multiple sources from the internet

Leave a comment