Skip to main content

Using Vagrant to Provision Terraform Using Ansible

By June 25, 2022September 12th, 2022No Comments

Using this blog and video we demonstrate using Vagrant to provision Terraform using Ansible. We will provision Terraform to deploy Docker containers on our Vagrant host, but, of course, Ansible could provision anything and not just Terraform. Vagrant is a Virtual Machine Manager and it has a variety of provisioners that allow you to customise the system on first boot. We do have an Ansible provisioner which can deploy a Playbook from Ansible installed on the Host. Ansible can be installed on Linux and macOS but currently not on Windows. Additionally, you may not want additional software installed on your host. There is also and Ansible_local provisioner which will install Ansible on to you guest system before running the Playbook. Whilst this is good, I do not like the idea of hardcoding the PLaybook to run inside of my Vagrantfile. This leads use to another possibility; have the shell provisioner install Ansible for you and add a variety of Playbooks into the directory that the Vagrantfile exists. This is shared with the Virtual Machine. We can also have a Playbook clone a git repository where you keep all the PLaybook you need.

On your host system you will need to create a project directory for the Vagrant file. The file could look something similar to this:

The Vagrantfile

# vi: ft=ruby:ts=2:ai:sw=2
$script = <<-SCRIPT
echo "Provisioning OS"
sudo apt-get update
sudo apt-get install -y ansible
Vagrant.configure("2") do |config| = "ubuntu/focal64"
        config.vm.provision "shell", inline: $script

As the system boots Ansible will be installed by the shell provisioner that we have added.

Ansible does not need any configuration if it working just with the localhost. So it is easy to execute and Playbooks that we want. The working directory where we added the Vagrantfile is mapped through to the /vagrant directory on the guest. If we add Playbooks and resources we need into this directory on your host. In the following Playbook we download the Hashicorp signing keys for their repos, add their repo allowing us to install Terraform into the VM. We also install Docker and add the current user to the Docker group. To make resource access easy we can use the Ansible git module to clone a repository which has the Terraform config files we need, the It is this file that is used to configure the Docker containers.

The Playbook:

. ---
- name: Setup Terraform on New Ubuntu 20.04 System
  hosts: localhost
  gather_facts: true
    - name: Update the APT Package Cache
      become: true
        update_cache: true
        cache_valid_time: 3600
    - name: Before we add the Hashicorp Repo - we add the signing key
      become: true
        url: ""
        state: present
    - name: We now add the Hashicorp Repo to Ubuntu
      become: true
        repo: "deb [arch=amd64] focal main"
        state: present
    - name: Install software from standard repos and hashicorp
      become: true
          - gnupg
          - software-properties-common
          - curl
          - terraform
    - name: We add the local USER to the Docker group
      become: true
        name: "{{ lookup('env', 'USER') }}"
        groups: docker
        append: true
    - name: We clone the course git repository
        repo: ""
        dest: "{{ lookup('env', 'HOME') }}/comptia-automation"
        version: main
    - name: We create the directory for terraform project
        path: "{{ lookup('env', 'HOME') }}/terraform/"
        state: directory
    - name: We create the web directory to store content
        path: "{{ lookup('env', 'HOME') }}/terraform/web"
        state: directory
    - name: We copy the terraform file from the course repo
        src: "{{ lookup('env', 'HOME') }}/comptia-automation/terraform/"
        dest: "{{ lookup('env', 'HOME') }}/terraform/"
    - name: Create the index page for the website
        dest: "{{ lookup('env', 'HOME') }}/terraform/web/index.html"
        content: This is my web page

The Terraform file,, is written the HCL format, it is also in my git repo:

The Terraform

terraform {
  required_providers {
    docker = {
      source = "kreuzwerker/docker"
      version = "2.16.0"

provider "docker" {
  # Configuration options

resource "docker_image" "nginx" {
  name = "nginx:latest"
  keep_locally = false

resource "docker_container" "nginx" {
  image = docker_image.nginx.latest
  name = "webserver"
  ports {
    internal = 80
    external = 8000
  volumes {
    container_path = "/usr/share/nginx/html"
    host_path = "/home/vagrant/terraform/web/"

Having run the Playbook we can logout and back in to join the correct groups and then enter our /terraform directory before running:

terraform init
terraform apply

The plan will be shown and once we accept the Docker container will be started and our Nginx web site will be running. To destroy the containers we can use:

terraform destroy

You can see by adding the Playbooks that you want to your system we can have the flexibility to configure anything that we want including using Vagrant to Provision Terraform using Ansible Playbooks.