Automate your virtual lab environment with Ansible and Vagrant

If you’re studying for your IT certifications, do technical research, or develop software you often need to set up a virtual lab environment. Therefore, I lately created an article about how to automate the creation and provisioning process of virtual machines with Vagrant. And I also created an article on how to automate all your Linux servers with Ansible. In this article, we’re combining those two amazing technologies. And I show you how you can easily automate a full lab environment containing multiple virtual machines.

How to use Vagrant with Ansible on Windows 10

If you’re running Vagrant on Linux, you can skip this part. But if you’re running Vagrant on Windows with VirtualBox or Hyper-V, you have a problem. Because Ansible is not running on Windows, you will need to run Vagrant with Ansible scripts on a Linux machine. Luckily, you can do this pretty easily with the Windows Subsystem for Linux (WSL2). Because the trick is to install Vagrant on your WSL machine and on your Windows 10, too. Note, that it needs to be installed exactly in the same version and it’s still considered a beta version at this time.

To install Vagrant on WSL just simply download the latest version at https://releases.hashicorp.com/vagrant/.

wget https://releases.hashicorp.com/vagrant/2.2.10/vagrant_2.2.10_x86_64.deb

sudo apt install ./vagrant_2.2.10_x86_64.deb

Next, you need to add a few environment variables according to https://www.vagrantup.com/docs/other/wsl.html. If you’re running bash, simply add them to your .bashrc file. On zsh you need to place them in your .zshrc file.

VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH=/mnt/c/Users/<your-personal-folder>
VAGRANT_WSL_ENABLE_WINDOWS_ACCESS=1

On Windows 10 with Hyper-V, set the default provider with the following environment variable.

VAGRANT_DEFAULT_PROVIDER=hyperv

Check if Vagrant is running on your WSL2 and can communicate to the Hypervisor on your Windows 10 by executing the vagrant command. If and error shows up, you probably haven’t loaded the environment variables correctly.

Install Ansible:

sudo apt-add-repository ppa:ansible/ansible

sudo apt update

sudo apt install ansible

Prepare the Vagrantfile to automate the virtual machine creation

Now let’s start with the creation of our Vagrantfile. If you’re not familiar with Vagrant yet, you should check out my tutorial about Vagrant, to learn the fundamentals. When you’re running Vagrant with VirtualBox, the configuration will look slightly different, because I’m using Hyper-V as my default provider. Any Virtualbox fans can just comment out the HyperV subconfiguration part.

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
  config.vm.define "master" do |subconfig|
    subconfig.vm.box = "generic/ubuntu2004"
    subconfig.vm.hostname = "master"
    subconfig.vm.provider "hyperv"
    subconfig.vm.network "public_network", bridge: "BRIDGE"

    subconfig.vm.provider "hyperv" do |h|
      h.enable_virtualization_extensions = false
      h.linked_clone = false
      h.vmname = "ubuntu_cluster_master"
    end

    subconfig.vm.provision "ansible" do |a|
      a.verbose = "v"
      a.playbook = "master_playbook.yaml"
    end
  end
end

If you later want to add more than one virtual machine, it’s useful to create a sub config for every single machine.

config.vm.define "master" do |subconfig|

We can automatically attach our virtual machine(s) to a virtual switch in Hyper-V with the following statement. Because the “BRIDGE” Interface is the name of my virtual switch that connects the virtual machine to my physical network adapter.

subconfig.vm.network "public_network", bridge: "BRIDGE"

This h configuration is part of the provider-specific configuration of the Hyper-V on Windows 10. For more information check out this blogpost.

    subconfig.vm.provider "hyperv" do |h|
      h.enable_virtualization_extensions = false
      h.linked_clone = false
      h.vmname = "ubuntu_cluster_master"
    end

Now we will create another subconfiguration to provision the machine with an ansible-playbook. This will contain all ansible instructions to provision our virtual machine. Vagrant automatically executes the ansible-playbook once the virtual machine is created the first time.

    subconfig.vm.provision "ansible" do |a|
      a.verbose = "v"
      a.playbook = "master_playbook.yaml"
    end

Create Ansible playbooks to provision the virtual machines

Now, we need to create your ansible-playbook that is used to provision our virtual machine. I’ve created an example of a playbook that will automatically install Docker. Of course, you can simply change the playbook to whatever your need is. By the way, you find useful examples on my GitHub repository ansible-boilerplates. Of course, you can simply use and modify them in a variety of different setups.

Because Vagrant completely handles the provisioning and authentication part, you don’t need to enter any passwords or public SSH keys.

---
- hosts: all
    become: yes
    tasks:
    - name: install prerequisites
    apt:
        name:
        - apt-transport-https
        - ca-certificates 
        - curl 
        - gnupg-agent
        - software-properties-common
    - name: add apt-key
    apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
    - name: add docker repo
    apt_repository:
        repo: deb https://download.docker.com/linux/ubuntu focal stable
    - name: install docker 
    apt:
        name: 
        - docker-ce
        - docker-ce-cli
        - containerd.io
        update_cache: yes
    - name: add userpermissions
    shell: "usermod -aG docker vagrant"

Start the virtual lab environment

Now, start the virtual lab environment. Just execute “vagrant up”, and Vagrant will create the virtual machine, install the box image, and provision it with the ansible-playbook. After that, you should see that all tasks are applied.

Let’s check if we’re able to log in to our virtual machine. To log in to a remote shell simply type in “vagrant ssh”. Then execute the command “docker –version”, to check if you’re able to execute any docker commands. Because if everything was successful, you will get the version number of docker.

3 thoughts on “Automate your virtual lab environment with Ansible and Vagrant”

  1. Thanks for great write up, I am trying to reproduce the same setup with Vagrant 2.2.14, however I have ran into an issue where running the Vagrant from Linux Volume e.g ~/vagrant ends up with error:
    Get-ACL : Method failed with unexpected error code 1.
    At \\wsl$\Ubuntu-20.04\opt\vagrant\embedded\gems\2.2.14\gems\vagrant-2.2.14\plugins\providers\hyperv\scripts\utils\VagrantVM\VagrantVM.ps
    m1:731 char:12
    + $acl = Get-ACL -Path $Path

    When I move the files to Windows volume e.g. /mnt/c/… I can get it started but Ansible Gathering Facts tasks will complain about Private Key permissions (0777) since it is now located in Windows side. and the play with end up with unreachable error.

    Have you found a workaround for that?

    Reply
  2. It is more effective if you add the variables as follows:

    #hyperv
    export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS=1
    export PATH=$PATH:/mnt/c/Windows/System32
    export PATH=”$PATH:/mnt/c/ProgramData/Microsoft/Windows/Hyper-V”
    export VAGRANT_DEFAULT_PROVIDER=hyperv

    Reply

Leave a Comment

I accept the Privacy Policy