Developing software as part of a team can sometimes be a pain, especially when the setup required to get that software to a working state is not trivial. Setting up dependencies, the state of the environment the application needs to run in and, worst of all, ensuring this configuration works just the same for everyone in your team, can feel like a fool’s errand.

Things can get very cumbersome too when you’re experimenting with a fiddly application that references conficting versions of libraries that may have to be installed in your machine. Installing the wrong version or doing so in the wrong place can swiftly unleash a world of pain that will sour your day or even your entire week.

Wouldn’t it be great if, at times like this, we could just throw everything away and start afresh? What’s more, wouldn’t it be beyond awesome that, once we had everything up and running smoothly, we could easily share it with everybody else in our team so they don’t have to go through the same excruciating pain as we did to get going, no matter the operating system or specific config they use in their dev computers?

No need to wonder, as today I intend to show you in just 5 minutes how you can realise this dream with Vagrant. Ok, ready? Go! ⏱

What is Vagrant?

Vagrant is a tool that allows you to capture the configuration of a development environment and apply this configuration to a virtual machine on which you will run the applications you’re developing. Since the setup of the VM is concisely described in a config file, you can be sure the same Vagrant box configuration will give you and your fellow devs the same environment to work on, irrespective of operating system or system configuration.

Setting up a Vagrant box

For this tutorial, we are going to spin up a Ubuntu VM running an Apache web server and we will make the web server available from the host.

Installation

To follow this tutorial you will need the following software installed in your machine:

  • VirtualBox
  • Ansible
  • Ruby

Download the version of Vagrant appropriate for your operating system.

Create a directory for the Vagrant box that we will be configuring.

$ mkdir ./vagrant
$ cd ./vagrant

Configuration

Create a file named Vagrantfile in this directory with the following contents:

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

Vagrant.configure("2") do |config|
  config.vm.define "ubuntu" do |ubuntu|
    ubuntu.vm.box = "ubuntu/xenial64"
    ubuntu.vm.hostname = "ubuntu"

    ubuntu.vm.network :private_network, type: "dhcp"
    ubuntu.vm.network :forwarded_port, guest: 80, host: 8080, auto_correct: true

    ubuntu.vm.provider "virtualbox" do |vb|
        vb.customize ["modifyvm", :id, "--memory", 1024]
        vb.customize ["modifyvm", :id, "--cpus", 1]
        vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
        vb.customize ["modifyvm", :id, "--ioapic", "on"] 
    end

    ubuntu.vm.provision "ansible" do |ansible|
        ansible.playbook = "setup.yml"
    end
  end
end

This will give us a barebones VirtualBox VM running Ubuntu Server 16.04 LTS. If we wish to install software onto it, like Apache, and run in additional box configuration steps when creating it, we need to write a separate file in the directory, called setup.yml, which is referenced from the Vagrantfile and will drive the box provisioning stage.

Copy this into setup.yml:

---
- hosts: ubuntu
  vars:
    ansible_python_interpreter: "/usr/bin/python3"
  remote_user: vagrant
  become: true
  tasks:
    - name: install packages
      apt: pkg={{item}} state=latest
      update_cache: yes
      with_items:
        - apache2

Your vagrant directory should now contain a Vagrantfile to specify the configuration of your Ubuntu VM and a setup.yml Ansible playbook to provision it.

Using Vagrant

Run this command in the directory where your Vagrantfile is located to launch the VM:

$ vagrant up

This will take a few minutes, as Vagrant has to download the Ubuntu ISO, load it into a new VirtualBox VM, configure and launch it. Once it’s done, navigate to the following URL in your browser:

http://localhost:8080/

If you can see the Apache server test page, the VM was successfully launched.

You can now access your VM by running the vagrant ssh command if you want to do further work on it.

When you get bored of it, just power it off with vagrant halt or destroy it completely with vagrant destroy. You can also take snapshots of the current running state of your VM with vagrant snapshot save <snapshot_name> and restore them with vagrant snapshot restore <snapshot_name>.

Here’s a cheatsheet of the essential Vagrant commands you should know:

  • vagrant init: copy a new Vagrantfile template into the current directory
  • vagrant up: launch/start a new VM
  • vagrant reload: reboot the VM and reload the configuration from the Vagrantfile
  • vagrant halt: stop a running VM
  • vagrant destroy: destroy an existing VM
  • vagrant ssh: SSH into a running VM

If you want to run these commands without parameters, you need to run them in the directory where the Vagrantfile is located. Otherwise, you’ll need to pass a Vagrant box ID to them. You can retrieve the list of all Vagrant boxes installed in your system by running vagrant global-status.

And that’s it. Time out! ⏱

Further Reading

P.S: Incidentally, I input the full text body of this article into a reading time calculator and it estimated it as 4 minutes, 29 seconds. It may take you a wee bit longer to get through the motions described in this article but I didn’t promise anything in that regard so… don’t call me a liar.