Start using Vagrant

I had the chance to spread the good word by talking about adopting DevOps in Symfony projects at the Symfony Live conference. The feedback was very good (for those who attended and have not done so yet, you can give some feedback here: You can also find the slides here: and the source code of the slides here:

One of the very good news is that I convinced many people (as observed on twitter) to start using vagrant after the conference. The slides gave a quick introduction, so let me give here a more detailed tutorial on how to start using vagrant.

Introduction to Vagrant

Vagrant is a ruby tool that makes the process of testing your code in a virtual machine VERY easy. You are concerned:

  • If you are a developer on a complex project with a specific system configuration on the production server that you want to reproduce in your development environment painlessly. This specific system configuration can be specific versions of some packages, a specific architecture or simply a specific OS.
  • If you are a Mac user! Because the chances that the project you develop will be hosted on a Mac are quite small…

It is quite amazing to see how many people develop on Macs to deploy on Linux systems and don’t use virtual environments. This has two obvious downsides:

  • you need to install a working development environment on your Mac which can quickly become a pain.
  • even with PHP applications, which are usually quite platform-independent, it is never truly the case and it is much better to avoid last-minute system-related surprises.

Install Vagrant

sudo gem install vagrant
  • Debian/Ubuntu
# Install Ruby, Ruby Gems and Vagrant
sudo apt-get install rubygems
sudo apt-get install ruby-dev
sudo apt-get install build-essential
sudo gem install vagrant
# Add the ruby gems path to your path
# Download and install VirtualBox
echo 'echo "deb maverick contrib" >> /etc/apt/sources.list' | sudo sh
wget -q -O- | sudo apt-key add -
sudo apt-get update
sudo apt-get install virtualbox-4.0
sudo apt-get install dkms

You should now be able to type vagrant in your terminal and see the list of tasks that you can do.

$ vagrant
  vagrant box                        # Commands to manage system boxes
  vagrant destroy                    # Destroy the environment, deleting the created virtual machines
  vagrant halt                       # Halt the running VMs in the environment
  vagrant help [TASK]                # Describe available tasks or one specific task
  vagrant init [box_name] [box_url]  # Initializes the current folder for Vagrant usage
  vagrant package                    # Package a Vagrant environment for distribution
  vagrant provision                  # Rerun the provisioning scripts on a running VM
  vagrant reload                     # Reload the environment, halting it then restarting it.
  vagrant resume                     # Resume a suspended Vagrant environment.
  vagrant ssh                        # SSH into the currently running Vagrant environment.
  vagrant ssh_config                 # outputs .ssh/config valid syntax for connecting to this environment via ssh
  vagrant status                     # Shows the status of the current Vagrant environment.
  vagrant suspend                    # Suspend a running Vagrant environment.
  vagrant up                         # Creates the Vagrant environment
  vagrant version                    # Prints the Vagrant version information

Now fetch the base Ubuntu Ludic 32 box provided by Vagrant. This make take a few minutes depending on your connection, since it consists in downloading around 700MB

$ vagrant box add base

Finally, to avoid permission problems with folder sharing between your host machine and your virtual environment, I highly recommend using NFS instead of VBox, which is the default protocol used by VirtualBox.

  • On Mac OS X, you do not need to do anything, NFS is already installed.
  • On Debian/Ubuntu, you just need to install the NFS package:
$ sudo apt-get install nfs-common nfs-kernel-server

Test on a first project

I set up a test project so that you can see how it works. Create a new folder called sflive2011vm. We will clone the configuration for our Vagrant Virtual Machine and then clone our actual project inside

$ cd sflive2011vm
$ git clone git:// .
$ git clone git://

Now all you have to do to test the project is

$ vagrant up

and after a few minutes, Vagrant will have started a virtual Ubuntu, installed all the packages needed and set up tha machine as described in the Puppet manifest. To verify that everything worked as planned just visit

That’s it!

Understand Vagrant

Let us now understand more deeply how Vagrant works:

The base box

The base box is simply a saved hard-disk of a Virtual Machine created with VirtualBox. It can contain anything but it needs at least :

  • Ruby
  • VirtualBox guest additions
  • Puppet
  • Chef

to be boot-strapped by Vagrant and then further configured by a Chef recipe or a Puppet manifest


This is the configuration file of Vagrant. The most useful options are port forwarding, provisioning solution (Puppet or Chef) and eventually NFS do |config| = "base"
  config.vm.forward_port("web", 80, 2011)
  config.vm.provision :puppet
  # config.vm.share_folder("v-root", "/vagrant", ".", :nfs => true)


The configuration of your VM is coded using Chef or Puppet. This ensures that you will reproduce exactly the same configuration in all your development VMs AND your production environment. Here is the Puppet manifest used in the example:

exec { "apt-get-update":
  command => "apt-get update",
  path => ["/bin", "/usr/bin"],

Package {
 ensure => installed,
 require => Exec["apt-get-update"]

class lighttpd
  package { "apache2.2-bin":
    ensure => absent,

  package { "lighttpd":
    ensure => present,

  service { "lighttpd":
    ensure => running,
    require => Package["lighttpd", "apache2.2-bin"],

  notice("Installing Lighttpd")

class lighttpd-phpmysql-fastcgi inherits lighttpd

  package { "php5-cgi":
    ensure => present,

  package { "mysql-server":
    ensure => present,

  exec { "lighttpd-enable-mod fastcgi":
    path    => "/usr/bin:/usr/sbin:/bin",
    creates => "/etc/lighttpd/conf-enabled/10-fastcgi.conf",
    require =>  Package["php5-cgi"],

  notice("Installing PHP5 CGI and MySQL")

class symfony-server inherits lighttpd-phpmysql-fastcgi

  package { ["php5-cli", "php5-sqlite"]:
    ensure => present,
    notify  => Service["lighttpd"],

  notice("Installing PHP5 CLI and SQLite")

class symfony-live-server inherits symfony-server

  file { "/etc/lighttpd/conf-available/99-hosts.conf":
    source => "/vagrant/files/conf/hosts.conf",
    notify  => Service["lighttpd"],
    require => Package["lighttpd"],

  exec { "lighttpd-enable-mod hosts":
    path => "/usr/bin:/usr/sbin:/bin",
    creates => "/etc/lighttpd/conf-enabled/99-hosts.conf",
    require => File["/etc/lighttpd/conf-available/99-hosts.conf"],
    notify  => Service["lighttpd"],

  notice("Installing and enabling Hosts file")

include symfony-live-server
notice("Symfony2 server is going live!")

Take home message

  • Vagrant is an essential part of the DevOps process: it is the solution to developing, testing and deploying in the same environment. It thus ensures a smoother transition of your project from the dev team to the ops team
  • Vagrant is EASY. And it is compatible with both Chef and Puppet
  • Vagrant is a must for Mac developers.