Use the Ansible configuration tool to effectively manage a Vagrant VM

Pairing Ansible and Vagrant eases the burden of deploying and managing VMs in your virtual environment. Follow these configuration management tips to get started.

A major aspect of overseeing virtual environments is effectively managing VMs. There are many different tools and...

techniques with which to do so, and configuration management tools, like Puppet and Chef, are gaining traction. Just because Puppet and Chef are the more well-known tools out there doesn't mean they're the best choices for your environment -- it's always good to keep your options open. In a previous article, we outlined how to deploy a Vagrant VM; now, we'll learn how to manage Vagrant VMs with Ansible.

First, put your server inventories in one file. The instructions for how to install software are in Ansible Playbooks and VM and container configurations are in VagrantFiles. Vagrant exists without Ansible as its own product, but here we'll discuss how to use them together.

Figure A illustrates this basic concept. You list all your targets on the Ansible Hub. Ansible Hub isn't an official name but generally refers to wherever you install Ansible. Then, the machine uses Secure Socket Shell (SSH) and remote shell (RSH) commands to set up a Vagrant VM with the VM definitions in VagrantFiles and whatever software you want to install on those machines in Ansible Playbooks.

Ansible Hub and target VM
Figure A. Ansible Hub and target VM software

Vagrant and target VMs

Use the following Vagrant command to launch a VM: vagrant up.

When you use Ansible, it configures and deploys a Vagrant VM to the targets you specify. These could be specific IP addresses or classes of machines, such as web servers. You maintain a list of targets in the inventory file. The main inventory file is /etc/ansible/hosts:

[webservers] ansible_user=root

There, you can group servers by function, so you can deploy functions to a specific set of servers.

SSH and agentless

Ansible uses SSH but does not require you to install an agent on the target machine. This is because Ansible issues RSH commands over the SSH port of the target instance. It's like typing apt-get, cp, update and so on on the remote machine, but from the Ansible Hub server instead.

There's no authentication other than SSH keys in the default setup. Connect to your Amazon Elastic Compute Cloud or other server like this:

ssh -i /root/.ssh/amazonKey.pem [email protected](AnsibleHub)

Then, simply copy the public key of Ansible Hub to the targets you wish to manage. In other words, copy ~/.ssh/, and append it to ~/.ssh/authorized_keys on the target machine. The target machine will then trust Ansible Hub and will allow it to issue commands using RSH without having to enter a password.

When you use Ansible, it configures and deploys Vagrant VMs to the targets you specify.

There's nothing too complex about this process; it's simply how you might write scripts to do administrative work. But Ansible and Vagrant have many options that make them both very flexible when handling complex situations that would be far too complicated to script.

Once you've listed your target servers in /etc/ansible/hosts, test them with the following command:

ansible -m ping all

Vagrant Ansible provisioning

To provision a VM with Vagrant Ansible, use the Vagrant init command to create a VagrantFile, and then the Vagrant up command to launch the VM using the definitions in VagrantFile. Ansible fits right into this model. If you look at the VagrantFile below, you'll notice it says config.vm.provision "ansible".

That tells Vagrant to use Ansible for further instructions. The VagrantFile below tells Ansible to install the ubuntu/trusty64 VM and the Ansible instructions in the YAML Ansible format file provisioning/playbook.yml against the target list of servers in the inventory file.

Vagrant.configure(2) do |config| = "ubuntu/trusty64" :private_network, ip: ""

config.vm.provision "ansible" do |ansible|
ansible.verbose = "v"
ansible.playbook = "provisioning/playbook.yml"
ansible.inventory_path = "provisioning/inventory.txt"


Here is the inventory file. There are various ways to generate this list automatically; here, we just list one host: default ansible_ssh_host=

Ansible Playbooks

The standard folder structure puts the Playbook in the provisioning folder. This Ansible file, taken from a HashiCorp example, installs the Network Time Protocol daemon (ntpd) server on the target Vagrant VM after it sets up the VM. HashiCorp wrote the open source Vagrant tool.

- hosts: eurovps
 - name: ensure ntpd is at the latest version
 yum: pkg=ntp state=latest
 - restart ntpd
 - name: restart ntpd
 service: name=ntpd state=restarted

If you run that with just Ansible -- without Vagrant -- it looks like this as it installs the ntpd server:

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: []

TASK [ensure ntpd is at the latest version] ************************************
ok: []

PLAY RECAP ********************************************************************* : ok=2 changed=0 unreachable=0 failed=0

Ansible and Vagrant

Then, when you run Vagrant again: vagrant up.

It follows the regular VM setup, which is what Vagrant does on its own, but it also sets up options in the YAML Ansible config. In other words, Ansible is a standalone tool, and Vagrant is a standalone tool. The Ansible-Vagrant connection brings the two together.

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...

Infrastructure as code

Using Ansible with Vagrant as infrastructure as code makes the build, maintenance and additional changes easier because configuration management instructions are stored in Playbooks and VagrantFiles, which are then checked into a software version control system. The whole infrastructure is written as an abstraction. Code, of any kind, is an abstraction, which makes it powerful and useful. So, while Ansible YAML is not a programming language per se, since it has no control loops and so forth, it is code.

Next Steps

Prevent mishaps with Windows configuration management

Learn more about Puppet architecture

Choose the best configuration management tool

Dig Deeper on Virtual machine provisioning and configuration