Note: I don't usually redo a blog post (the original will remain online for ever as far as I'm concerned) but I think that the landscape has changed enough in the last couple months that I needed to rewrite this post using a better solution.

Ideally, we should all be developing our code in our own little space on our own little local server. This allows us to easily make changes without messing up production code or stepping over other's work. This is usually cost prohibitive so we're "forced" to use virtual machines to make this a reality.

The problem we face is that each developer needs to have a virtual machine that is setup exactly (or nearly exactly) like our production server. This requires a long list of configuration changes that need to be made on every machine. For example, install the apache package, update this configuration file, setup MySQL so you can access the databases remotely. Then we run into more problems when additional changes are needed because the developer has to take time out of their schedule to make them on each machine. There are also passwords that have to be remembered and /etc/host changes that need to be made. You'll be in even worse shape if the deployment consists of multiple VMs.

Enter Vagrant

Vagrant is here to help us make this process easier. With Vagrant we can easily create a VM with all the packages and items we need in order to get our project up and running. It will then, just as easily, allow us to delete the virtual machine so we don't have it eating up space on our computer (with the cost of hard drives being what it is this argument might be completely academic).

The real benefit is that you will no be a slave to the "it works on their computer" excuse. This is a total cop out and really only hurts your internal and external customers. Because every development box has exactly the same configuration (or can in a matter of minutes) this extra variable is removed when it comes time to fix a bug.

On top of that Vagrant gives us some other really cool features. The best one in my opinion is that it automatically redirect your working directory to a directory on the VM. That means you can use all your native applications (GitHub for Windows/Mac, Sublime Text 2, MySQL Workbench, etc.) and truly work the way you want to work.

Prerequisites

If you don't already have it installed install VirtualBox and Vagrant. I'll also be using a copy of Wordpress as an example or you can download all the code for this setup from this github repository https://github.com/warren5236/WordpressWithVagrant.

Creating a Basic Setup With PuPHPet.com

When I wrote Getting Started with Vagrant I complained about the fact that Vagrant didn't have a nice user interface. I've come to view puphpet.com as that nice interface. It's still rapidly evolving but extremely easy to use to create a basic box and then customize it when you need additional features. puphpet.com uses [puppet][http://puppetlabs.com/] instead of the bootstrap file I used so dependancies are more easily defined but the configuration file is a little harder to parse. This section will step you through getting the correct settings so we can install Wordpress.

Basic Set Up

For this example, we're going to use Ubuntu Precise 12.04 x64 so click the radio button next to this option in the "Operating System" section.

Inside the HTTP server options we're going to want to setup a basic virtual host so we can more easily manage the settings for the site. By default PuPHPet defaults to using awesome.dev as the server name. You can keep this default setting but it requires that you add an entry in your hosts file that redirects awesome.dev to the correct IP address (192.168.56.101 in this case). I'm not a fan of having to add entries to my hosts file because it can become a real mess so I find it better to use <xip.io> for this. In this case, I'm using wordpress.192.168.56.101.xip.io. We also want to change our Document Root setting from /var/www/ to /var/www/public/ so we can protect our settings from the public.

Scroll down to the "Database" section and enter a root password. In this case we're going to set this to rootpass.

PuPHPet will also create a new database for us and an associated user. Let's make a database named wordpress with a user named wordpress and a password of wordpress (I know it's not super secure but it's easy to remember).

After that has been entered scroll down to the bottom of the page and click the "Create My Manifest!" button. This will download a zip file that contains all the supporting files that we need. Extract the zip file and open a command prompt with this as the current directory.

What Do We Have

Now that we have extracted our PuPHPet setup we're presented with two directories and a couple files. The import pieces are the Vagrantfile which Vagrant uses to create it's VM, the modules directory which puppet uses to apply the various items we need to have installed, and the manifests directory which contains the setting file that puppet uses to apply the various modules. It's important that the Vagrantfile is located in the root of the project you're working on so Vagrant can find it when it's needed.

'Install' Wordpress

Because we have the root MySQL password listed in the PuPHPet setup (it's in the ./manifests/default.pp file if you're so inclined) we're going to want to protect it from prying eyes. The best way to do this is to keep it outside the directory that Apache is going to be serving. To do this we're going to create a public directory inside our working directory and then put all the Wordpress files there. If you didn't change the Document Root to /var/www/public when you created your PuPHPet setup you'll need to find the following section in your ./manifests/default.pp file and change it.

Original

apache::vhost { 'wordpress.192.168.56.101.xip.io':
  server_name   => 'wordpress.192.168.56.101.xip.io',
  serveraliases => [
],
  docroot       => '/var/www/',
  port          => '80',
  env_variables => [
],
  priority      => '1',
}

New

apache::vhost { 'wordpress.192.168.56.101.xip.io':
  server_name   => 'wordpress.192.168.56.101.xip.io',
  serveraliases => [
],
  docroot       => '/var/www/public/',
  port          => '80',
  env_variables => [
],
  priority      => '1',
}

Vagrant Up

Now it's time to create the VM. Type vagrant up into the command prompt in your project directory (the one with the Vagrantfile in it) and you'll get the following:

Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'precise64'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.

[Shortened so people don't go insane]

At the end of this you'll be brought back to the command prompt and if you attempt to access http://wordpress.192.168.56.101.xip.io on your computer you should see the Wordpress install screen:

Go through the process of creating the site, add a couple test posts, and then come back to this article.

Vagrant ssh

Now that we have Wordpress up and running it's time to make a copy of our database so we can easily restore it the next time we need to created this virtual box. In order to do that we need shell access to the server. Type the following into the command line:

vagrant ssh

This will automatically log you into the VM and you should see something like the following:

Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic-pae i686)

 * Documentation:  https://help.ubuntu.com/
Welcome to your Vagrant-built virtual machine.
Last login: Fri Sep 14 06:22:31 2012 from 10.0.2.2
vagrant@precise32:~$ 

Now that you have direct access to the VM. Feel free to play around all you want. Remember that anything located in the /var/www/ directory is mirrored to your working directory so you can damage it but everything else can easily be restored.

When you're done run the following commands

mkdir /var/www/data 
mysqldump -uroot -prootpass wordpress > /var/www/data/initial.sql

This will make a backup copy of our Wordpress database so we can easily restore it the next time we recreate the VM.

Just to make sure everything is working we can look at our working directory and see that the sql file has been stored.

In order to leave the SSH session just type in exit.

Vagrant Halt

The VM isn't just idle. It's actually using some memory and CPU cycles just sitting there. So we don't tax our system too much we can shutdown VMs when we aren't using them. This is done using the vagrant halt command.

If we open VirtualBox before issuing this command we'll see that the VM is running:

When we run the command we'll see the following in the command line:

vagrant halt
[default] Attempting graceful shutdown of VM...

Then if we look back at the VirtualBox window we'll see this:

When we need to use this VM again we can just run vagrant up and it will be booted.

Vagrant Destroy

If you're like me you have a lot of projects going all the time but you don't always have enough room on your laptop hard drive for them. So from time to time you'll need to clean out the older images. In order to do this we'll use the vagrant destroy command. When we issue this command the following should be displayed:

vagrant destroy
Are you sure you want to destroy the 'default' VM? [y/N] y
[default] Destroying VM and associated drives...

After this has run we can check in VirtualBox to see that the VM is no longer there:

I would actually recommend trying this occasionally even if you don't need to because it provides you with an "opportunity" to test your backups and to make sure the VM is recreated with all the packages it needs.

Setting Up Puppet to Automatically Import the Initial.sql File

If you want to automatically import you initial.sql file you need to open the ./manifests/default.pp and locate the section that looks like this.

mysql::db { 'wordpress':
  grant    => [
    'ALL'
  ],
  user     => 'wordpress',
  password => 'wordpress',
  host     => 'localhost',
  charset  => 'utf8',
  require  => Class['mysql::server'],
}

This is the section that creates the wordpress database and the wordpress user. We're going to add another key/value pair that sets sql to /var/www/data/initial.sql. When you're done it will look like the section below.

mysql::db { 'wordpress':
  grant    => [
    'ALL'
  ],
  user     => 'wordpress',
  password => 'wordpress',
  host     => 'localhost',
  charset  => 'utf8',
  require  => Class['mysql::server'],
  sql      => '/var/www/data/initial.sql'
}

Vagrant Up Again

A couple months go by and our client want something changed. Thankfully we're using vagrant so we can quickly get up and running again. All we have to do is run vagrant up again and the site will be restored to exactly the state it was in when we created the backups of the data. If you don't trust me try it.

Closing

As you can clearly see Vagrant provides several features that I think will make it a mainstay in everyones toolkit for years to come. When it's paired with Puppet it's even more powerful and provides an amazing way to make sure everyone is using the same version of your dependancies. I've started using it for all my current projects and I'll be using it in any of my future projects as well.