Your development environment with Vagrant and Ansible

Posted on Nov 1, 2013
tl;dr: My Journey into infrastructure as code


My development workflow has always been evolving. As a software developer I’m always trying to find the best combination of tools and configuration to be more efficient and reduce the number of steps of getting code written in my computer into production. I remember those days when I preferred to write code and test it directly in production. My knowledge about how things worked in those years was so limited that I didn’t want to deal with any unknown error.

After some time I realised how wrong this was and started using tools like XAMPP/WAMP/MAMP to recreate a LAMP production environment in my machine. The applications were simple, no obscure configurations or dependencies were needed. This way of coding in local and shipping to production after testing locally seemed to be the right way to go, at least for a while. After joining Clear Books and started working with our application framework, things went more complicated. A simple LAMP stack wasn’t enough to get the whole application up and running, a lot of custom configuration were needed. If you were a linux user, you can just get a copy of a preconfigured virtual machine and start developing in a virtualized environment, on the other hand, if you wanted a high responsive native installation, you will need to spend around a day, and the help from another developer to get it ready. This approach was wrong.

The Enlightenment

Right on time when I was having these issues and thinking of how to speed up the development process from getting a fresh clean OS installation to a fully complete development machine, I stepped into this project from GitHub called Boxen. Boxen pretends to automate all the tedious tasks of installing all the tools and dependencies for you. When Will Farrington was presenting Boxen at PuppetConf 2012, I literally jaw dropped after hearing how this piece of software was able to automate all the things for GitHub, and hopefully for you too. It is a great project but for now it works only on OS X, so I had to discard this at the moment.

Some time later I read a post on the Tuenti corporate blog about their full development workflow , and I was surprised to know that they were facing the same situation as me. The time to get a new developer ready to work was long, then they moved to local development servers per team, which was good but not enough, they needed more isolation. In their actual workflow now each developer can have their own environment called “Tuenti-in-a-Box” which uses Vagrant for creating, managing and distributing portable environments using virtualization and Puppet, a configuration management tool widely used by DevOps professionals.

The Vagrant and Ansible solution

After doing more research on Vagrant and Ansible, a configuration management tool which I first heard from another developer at Clear Books, I decided to use both as my combination for setting up a fast and improved development environment.

Some of the characteristics I wanted to achieve with this new workflow were:

  • Repeatable: By having all the setup and configuration task together with the source code, you are pretty sure that every time you run them it will be the same result.
  • Verifiable: Since this configuration is written by people who know the system internals, it makes this approach verifiable.
  • Isolated: The entire environment is isolated in a virtual machine.
  • Easy: Vagrant up: easier? impossible.
  • Fast: Since there are no processes where human needs to interact, the speed will be delimited by your hardware and internet connection.


Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent workflow to help maximize the productivity and flexibility of you and your team [1].

Basically what vagrant will enable you to do is creating configuration files (Vagrant file) with a set of rules that will define how a virtual machine should be built. A simple example of a Vagrant file is:

Vagrant.configure("2") do |config| = "Ubuntu-12.04-x86_64"
	config.vm.box_url = "" :private_network, ip: ""
	config.vm.provider :virtualbox do |v|
		v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
		v.customize ["modifyvm", :id, "--memory", 256]
		v.customize ["modifyvm", :id, "--name", "My [project name] Development machine"]

	config.vm.synced_folder "./", "/var/www"
	config.vm.provision :shell, :inline =>
			"if [[ ! -f /apt-get-run ]]; then sudo apt-get update && sudo touch /apt-get-run; fi"

	config.vm.provision :shell, :inline => 'echo -e "mysql_root_password=somePassword controluser_password=somePassword" > /etc/phpmyadmin.facts;'

	config.vm.provision :ansible do |ansible|
		ansible.verbose = true
		ansible.inventory_path = "path/to/ansible/hosts"
		ansible.playbook = "path/to/ansible/site.yml"



Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

Ansible’s goals are foremost those of simplicity and maximum ease of use. It also has a strong focus on security and reliability, featuring a minimum of moving parts, usage of Open SSH for transport (with an accelerated socket mode and pull modes as alternatives), and a language that is designed around auditability by humans – even those not familiar with the program.[2]

For the use case that I’m talking in this post, Ansible will contain all the specifications of the tools and configurations we needed to install for the web application. This configuration is hold on files called Ansible playbooks. This is an example of piece of an Ansible playbook for setting up a web server with php:

# These tasks install http and the php modules.
- name: Install http and php etc
  yum: name={{ item }} state=present
	  - httpd
	  - php
	  - php-mysql
	  - git
	  - libsemanage-python
	  - libselinux-python

- name: insert iptables rule for httpd
  lineinfile: dest=/etc/sysconfig/iptables create=yes state=present regexp="{{ httpd_port }}" insertafter="^:OUTPUT "
	  line="-A INPUT -p tcp  --dport {{ httpd_port }} -j  ACCEPT"
  notify: restart iptables

- name: http service state
  service: name=httpd state=started enabled=yes

- name: Configure SELinux to allow httpd to connect to remote database
  seboolean: name=httpd_can_network_connect_db state=true persistent=yes

One of the differences that made me chose Ansible from Puppet was the simplicity of setup. Ansible doesn’t require a puppet agent in the guest machine which was a great plus. The other characteristic was the language used to write the configuration files (ansible playbooks), while puppet uses a custom json syntax, Ansible chose yaml with a good set of best naming practices to manage all the instructions to run in the guest machine.


The days of hand-crafting your development environment have ended, the complexity of new information systems is growing at big scale and solutions like Vagrant and Ansible are just one of the options to achieve a configurable, reproducible and portable environment, tools like puppet, chef, salt stack should be considered too.

Configuration and infrastructure should be treated as code in order to avoid time-consuming tasks and lower error rates. Development environments should imitate the production as much as possible, and your testing and staging environment should do the same.


[1] Vagrant. (Nov 12, 2013). Vagrant Docs: Retrieved from:

[2] Ansible Works. (Nov 12, 2013). Ansible Works Documentation: Retrieved from: