Start using Vagrant

17 March 2011

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: http://joind.in/talk/view/2756) You can also find the slides here: http://www.slideshare.net/mobile/fabrice.bernhard/adopt-devops-philosophy-on-your-symfony-projects and the source code of the slides here: https://github.com/fabriceb/sflive2011-devops)

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
PATH=$PATH:/var/lib/gems/1.8/bin
# Download and install VirtualBox
echo 'echo "deb http://download.virtualbox.org/virtualbox/debian maverick contrib" >> /etc/apt/sources.list' | sudo sh
wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -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
Tasks:
  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 http://files.vagrantup.com/lucid32.box

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://github.com/fabriceb/sfLive2011vm.git .
$ git clone git://github.com/fabriceb/sfLive2011.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 http://127.0.0.1:2011/hello/master

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

Vagrantfile

This is the configuration file of Vagrant. The most useful options are port forwarding, provisioning solution (Puppet or Chef) and eventually NFS

Vagrant::Config.run do |config|
  config.vm.box = "base"
  config.vm.forward_port("web", 80, 2011)
  config.vm.provision :puppet
  # config.vm.share_folder("v-root", "/vagrant", ".", :nfs => true)
end

Provisioning

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.
Filed under : Programming — by @ 12 h 15 min

6 Comment »

  1. Jeff McCune say :
    18 March 2011

    Great article, I’ve actually been playing with Vagrant myself these past few days. The support for multiple VM’s in a single Vagrant project file is looking to be really good as well.

    I’ve posted some VM’s that work well with two ethernet interfaces for the host only networking support. If you’re working with Enterprise Linux systems, give these a try:

    http://puppetlabs.s3.amazonaws.com/pub/centos5_64.box

    5 h 52 min

  2. Jeff McCune say :
    18 March 2011

    Sorry, that should be:

    vagrant box add centos5_64 http://puppetlabs.s3.amazonaws.com/pub/centos5_64.box

    5 h 53 min

  3. zenmatt say :
    25 March 2011

    Great article. We’re huge vagrant fans and if any of your readers are looking for a tool that can help them move a Vagrant server to Amazon, Rackspace, Slicehost, Linode, etc – checkout Blueprint. It’s opensource and available at http://www.devstructure.com.

    2 h 08 min

  4. Nilesh say :
    27 September 2011

    Thanks for are at writeup on vagrant. I have been trying vagrant for last few days and it seems promising.

    I found an issue re: puppet group and a workaround related to this. described at link below. Thanks again.

    https://github.com/fabriceb/sfLive2011vm/issues/1

    15 h 13 min

  5. pau1_m say :
    14 December 2012

    On OS X this didn’t work for me on the lastest version of vagrant. Made the following changes to get it working.

    Renamed base.pp to default.pp in the manifests directory

    and changed the line

    config.vm.forward_port(“web”, 80, 2011)

    to

    config.vm.forward_port 80, 2011

    in Vagrantfile

    Also set to host only because NFS seemed to demand it

    config.vm.network :hostonly, “33.33.33.10″

    Cheers for the awesome work :)

    21 h 51 min

  6. Build a zen command-line environment with git, tmux, oh-my-zsh, mosh (and docker) | Theodo, développement agile symfony say :
    24 February 2014

    [...] The experiment is bootstrapped with the now classic installation of vagrant and virtual box. [...]

    14 h 58 min


Leave an answer