How to setup a dev environment using Vagrant & Puppet (Part I)

Vagrant

Vagrant is a great tool for spinning up different dev environments without polluting your own local machine with gems and packages from different projects. It is also great for sharing the same environment across your entire team without having to going through the pain of manual setup every time you on-board a new team member.

You can use providers/platforms such as VMWare, VirtualBox, AWS, etc to run your VM. If you are a first-time user, installing VirtualBox is probably your best option to get started.

After you’ve installed VirtualBox and Vagrant, let’s create a folder where you want to initializing a base machine.

$ mkdir my-project-dev-box
$ cd my-project-dev-box
$ git init
$ vagrant init precise32 http://files.vagrantup.com/precise32.box

Those commands will create a plain Ubuntu 12.04 box and generate a Vagrantfile in my-project-box folder. It will also initialize a git repository since we’ll need that later down the line to add modules.

But the first thing we’ll do now is add custom hostname in the config block to avoid getting confused if you spin up more Vagrant machines in the future. I like to have the project’s name in the hostname so you can easily identify it (same as the folder name):

config.vm.hostname = 'some-project-dev-box'

Since we’ll be using this for a particular dev environment, we need more than just a plain Ubuntu box. So let’s look at how we’d go about installing other packages and software.

Vagrant supports many different provisioners/IT automation tools such as Ansible, Chef, Puppet, or even a plain old shell script to help us automate this process. For the purpose of this post, we’ll use Puppet since IMHO it has the easiest learning curve.

Puppet

To use Puppet for provisioning, add this block in the Vagrantfile:

config.vm.provision :puppet do |puppet|
    puppet.manifests_path = 'puppet/manifests'
    puppet.module_path    = 'puppet/modules'
    puppet.options        = '--verbose'
end

So as you might have guessed, we’ll need a puppet directory with two sub-directories manifests and modules. Manifests will contain a default.pp file which tell Puppet which modules to install and how:

|   .Vagrantfile
\---puppet
    +---manifests
    |       default.pp
    \---modules

Modules are basically just re-usable instructions for how to install specific piece of software. You can create your own modules or just grab some 3rd party modules from the Example42’s repository, Puppet Lab’s official repository, or just from other folks on GitHub.

There are basically three ways of installing/using these modules. You can either clone or just copy/paste the module in the modules folder, you can add it as a git submodule or use the puppet module tool. I’ve never tried the last one since it doesn’t work on Windows.

This is where I’ll stop for now. In my next post, I’ll talk about installing specific modules and how to overcome some common gotchas while configuring them. Meanwhile, here’s what our basic Vagrantfile looks like at this point:

Vagrant.configure('2') do |config|
  config.vm.box      = 'precise32'
  config.vm.box_url  = 'http://files.vagrantup.com/precise32.box'
  config.vm.hostname = 'some-project-dev-box'

  config.vm.provision :puppet do |puppet|
    puppet.manifests_path = 'puppet/manifests'
    puppet.module_path    = 'puppet/modules'
  end
end

If you wanted to you can boot your VM and ssh into it just like any other Ubuntu machine:

$ vagrant up
$ vagrant ssh

Although at this point, there’s not much to see. We’ll get to the fun stuff in part II. Stay tuned!

If you have any questions or comments, please post them below. If you liked this post, you can share it with your followers or follow me on Twitter!