Using Vagrant and Ansible to Configure Development Machines

phpMelb - April 15th, 2014

Damien Buttler

  • @doublehops

What Advantages are there in Running Virtual Machines for Development?

  • Scripted environments that can shared with team with each environment identical
  • No need to have PHP, Nginx or other packages installed on host machine
  • Each project can have unique environments and package versions
  • Scripts can be used to configure production environments

Using Vagrant and Ansible for Configure Environments

  • Vagrant as the virtual machine handler
  • Ansible is the configuration tool

Together they make small work out of a complex task

What do we Need?

  • Virtual machine package such as Virtualbox or VMware
  • Vagrant
  • Ansible

*All software runs on Windows, Mac and popular *nix systems.


Vagrant is a lightweight, easy to use wrapper that will create a virtual machine, install an OS and pass control to a provisioner script for configuration.

Configure Vagrant with a Single File

File: ./Vagrantfile = "wheezy"

config.vm.box_url = ""

config.vm.hostname = 'debian-web'; :private_network, ip: ""

config.vm.synced_folder "./www", "/var/www", id: "vagrant-root", :group=>'www-data', :mount_options=>['dmode=775,fmode=775']

config.vm.provision "ansible" do |ansible|
   ansible.playbook = "provisioners/playbook.yml"
   ansible.inventory_path = "provisioners/ansible_hosts"

Common Vagrant Commands

  • vagrant init
  • vagrant up
  • vagrant provision
  • vagrant status
  • vagrant ssh
  • vagrant reload
  • vagrant suspend
  • vagrant halt
  • vagrant destroy


Ansible is an automation tool for configuration and deployment.

  • Is an alternative to Puppet and Chef
  • Works over SSH so no need for agents on remote hosts
  • Uses YAML markup for commands
  • Great documentation
  • Very logical commands and syntax

Example Playbook

File: provisioners/playbook.yml

- hosts: webservers
  user: vagrant
  sudo: yes

    - roles/common/vars/vars.yml

    templates_dir: "roles/common/templates"

    - include: roles/common/tasks/base.yml
    - include: roles/common/tasks/environment.yml
    - include: roles/common/tasks/add_ppas.yml
    - include: roles/common/tasks/php.yml
    - include: roles/common/tasks/nginx.yml
    - include: roles/common/tasks/mariadb.yml

Example Task (Add PPAs)

File: provisioners/roles/common/tasks/add_ppas.yml

  - name: Add dotdeb main
    apt_repository: repo='deb wheezy all' state=present
  - name: Add dotdeb main src
    apt_repository: repo='deb-src wheezy all' state=present
  - name: Add dotdeb php55
    apt_repository: repo='deb wheezy-php55 all' state=present
  - name: Add dotdeb php55 src
    apt_repository: repo='deb-src wheezy-php55 all' state=present

  - name: APT | Install DotDeb key
    apt_key: url='' state=present
    tags: dotdeb

Example Task (Nginx)

File: provisioners/roles/common/tasks/nginx.yml

  - name: Nginx | Install Nginx
  - name: Nginx | Check vhosts path exists
    file: dest=/etc/nginx/sites-available state=directory
  - name: Nginx | Copy vhost files
    copy: src="{{ templates_dir }}/nginx/sites-available/webserver1" dest=/etc/nginx/sites-available owner=root group=root  mode=600
    - nginx-restart
  - name: Nginx | Create vhost symlinks
    file: path=/etc/nginx/sites-enabled/webserver state=link src=/etc/nginx/sites-available/webserver1
    - nginx-restart
  - name: Nginx | Remove default vhost
    file: dest=/etc/nginx/sites-available/default state=absent
  - name: Nginx | Remove default vhost enabled symlink
    file: dest=/etc/nginx/sites-enabled/default state=absent
  - name: Nginx | Ensure directory exists
    file: dest=/var/www state=directory
  - name: Nginx | Ensure Nginx is running


Example Task (PHP)

File: provisioners/roles/common/tasks/php.yml

  - name: Install PHP5
    apt: pkg={{ item }} state=latest force=yes
      - php5-fpm
      - php5-mysql
      - php5-cli
      - php5-curl

  - name: PHP | Copy PHP config file
    copy: src="{{ templates_dir }}/php/php.ini" dest=/etc/php5/fpm/php.ini owner=root group=root force=yes
    - php5-fpm-restart

Example Handler (PHP)

File: provisioners/roles/common/handlers/php.yml

  - name: php5-fpm-start
    service: name=php5-fpm state=started
  - name: php5-fpm-restart
    service: name=php5-fpm state=restarted
  - name: php5-fpm-stop
    service: name=php5-fpm state=stopped

Live Demo

  • Create fresh working path
  • Checkout project from Github
  • Add record to /etc/hosts ( development)
  • Run `vagrant up`
  • Point browser to http://development/



Damien Buttler

  • @doublehops