Well... enough with the sedentary life, I'm going Vagrant.

.. oh and by Vagrant I mean this project ;)

I've heard a lot of people talk about this project lately, and I read the feature list and found pretty it interesting. A very quick summary of the features would be that it can automatically create customized VirtualBox VMs and provision them with Chef/Puppet.

Today I'm leaving my home behind.

The cool thing about Vagrant is that you can create a full dev environment, with every tool/library required for development already installed and ready to use, then package this up (and the VM's configuration) into a single file that you can use as a template. So, you can have one single file that you distribute to your dev team and everyone can then use the same environment to build, abuse and break ... but that environment is on their own computer! (with the hope that the developers can minimally manage the VM) That means that a heavy SQL request won't be killing the single development server, and also that a devloper can bring a dev server along on the bus, plane or train to continue work while offline.

It also means you can build a VM that's all ready for a live presentation in a conference and remove the really annoying dependency on Internet (which, we all know never works as expected at conferences).

I'm using Ubuntu 10.10 (Maverick) as the host OS. So all commands found below will deal with that OS. I'll be building a cardboard box for my puppet manifests to live in.

Getting started

So, where do we start? Got your cardboard, your scissors and some glue? ... OK, now for the basics: the Vagrant web site has a pretty good starter guide that I suggest you read diagonally before installing the thing. This way you'll be more familiar about Vagrant lingo. You can refer to the guide later to really try the suggested commands.

The project's web site claims that you simply blink your eyes twice and Vagrant is installed on your computer. However, I'm using Ubuntu Maverick here, and things didn't go as smoothly for me as "gem install"-and-we're-ready! I found out this VirtualBox + Vagrant install howto for Maverick that filled in [almost] all the gaps.

Since the writing of the above howto, Vagrant and VirtualBox have progressed, and so have the requirements. So you must change the VirtualBox package name from virtualbox-4.0 to virtualbox-4.1.

I also added a line to the end of my ~/.bashrc script so that the vagrant binary is always available without its full path:

PATH=$PATH:/var/lib/gems/1.8/bin

A step that is missing from the howto is to add yourself to the vboxusers group. This will let you configure things like usb devices and get you rid of pesky warning messages in VirtualBox's Gtk interface:

adduser your-username vboxusers

Then logout of your X session and login again so that this new group applies to your session.

Now, there's one final thing that is not mentioned in the howto. I'm using Vagrant as an unprivileged user on my machine, and upon the first invocation, I ran into this error:

/var/lib/gems/1.8/gems/net-ssh-2.1.4/lib/net/ssh/key_factory.rb:38:in `read': Permission denied - /var/lib/gems/1.8/gems/vagrant-0.8.8/keys/vagrant (Errno::EACCES)
[cut... huge ruby backtrace here]

To fix the above issue, I simply made the file readable to the vboxusers group like so:

sudo chgrp vboxusers /var/lib/gems/1.8/gems/vagrant-0.8.8/keys/vagrant
sudo chmod g+r /var/lib/gems/1.8/gems/vagrant-0.8.8/keys/vagrant

Building virtual machine templates

Once you have Vagrant all setup on your computer, you can go and find base boxes online (e.g. virtual machine templates) that you can download.

However, I wanted to build my own VM templates to customize them to my own liking/needs, so I continued searching info about how to build base boxes. There's some very interesting info on this site on how to build a base box "manually" for CentOS. I didn't use it directly, but I'm thinking of using it as an example for building Windows XP VMs later.

Now the reason I didn't use the above link is that I found out there was a project that automated everything for a whole bunch of OSes! This project is called "veewee". It's another ruby gem that adds a new subcommand to Vagrant so that you can create base boxes in a really neat (fully automated and scripted -- possible to redo things without typos or forgotten elements) and painless way. Here's an install + usage howto for veewee.

Creating a puppet client base box

mkdir vagrant-squeeze && cd vagran-squeeze
vagrant basebox define debian-squeeze 'Debian-6.0.3-amd64-netboot'
vim definitions/debian-squeeze/definition.rb  # optional, Set number of CPUs and quantity of RAM and disk here. Note: I also changed :hostiocache to 'on' here since I'm using ext4 on my host computer
vim definitions/debian-squeeze/preseed.cfg  # optional, Change language settings, keyboard map and .deb repository mirror hostname here. Some d-i knowledge helps, but you definitely don't need to be an expert to simply change the settings.
vagrant basebox build debian-squeeze
vagrant basebox validate debian-squeeze
vagrant basebox export debian-squeeze
vagrant box add debian-squeeze debian-squeeze.box
vagrant basebox destroy debian-squeeze  # Cleanup when we're done

Ok, you followed me up to this point? We now have a debian-squeeze.box file that contains a basic Debian Squeeze template that we imported as debian-squeeze. Let's build on that to add the Puppet client:

mkdir puppet-squeeze && cd puppet-squeeze
vagrant init debian-squeeze
mkdir manifests
cat > manifests/debian-squeeze.pp <<EOF
package { 'puppet': ensure => installed }
exec { "/bin/hostname puppet-squeeze": }
file { "/etc/hostname":
  ensure => present,
  content => "puppet-squeeze",
}
exec { "/bin/sed -i 's/debian-squeeze/puppet-squeeze/g' /etc/hosts": }
EOF
sed -i 's/^end$/  config.vm.provision :puppet\nend/' Vagrantfile  # This enables puppet provisioning of the VM
vagrant up

You should now have a VM up and running with puppet installed on it. You can now use vagrant ssh to ssh into it and start playing around with puppet!

To make things easier to re-create later, I strongly recommend putting all of your customizations in the debian-squeeze.pp manifest file (or in other .pp files that you import in debian-squeeze.pp) instead of manually via ssh. You probably want to keep this VM as simple as possible, though, since it's meant as a template. All project-specific customizations can (and probably should) be done later when provisioning a VM with 'puppet-squeeze' as a template.

The last step is to package this up into a box and to import it as a base box:

vagrant package  # should gracefully shutdown the VM if it's still running
vagrant box add puppet-squeeze package.box
vagrant destroy

The resulting package.box is around 300Mb on my laptop. It may be possible to shrink this down a little bit by zeroing out the virtual disk and by asking VirtualBox to compact the disk image file. For more info on how to do this, check out the comments on the Maverick vagrant howto on www.theodo.fr that's linked at the beginning of this post.

As an optional cleanup step, you could get rid of the first template with vagrant box remove debian-squeeze, but depending on what you'll do with Vagrant, you might want to skip this step and just keep the thing laying around. Also, if you ever want to rebuild the puppet-squeeze base box, you'll need the debian-squeeze template.

You're now all set! You can create a new vagrant project with vagrant init puppet-squeeze and start manipulating puppet.