Spinning up useful VMs quickly with Vagrant, Puppet and Puppet Forge

May 14, 2014 Brian Kelly

Often during development it can be convenient or even necessary to spin up a virtual machine. And if you’re on a project with multiple developers you will likely want each to have their own instance. Doing that manually can require a lot of time. We want to automate this as much as possible so we’re not wasting time. Tools like VirtualBox, Vagrant and Puppet make this not only quick but repeatable and easy to share.


You’ll need to have the following installed already:

  1. VirtualBox to run your VMs
  2. Vagrant to automatically configure VMs
  3. Ruby to run the Ruby-based tools you’ll be using
  4. Bundler for managing some Ruby dependencies

Note: I recommend you install VirtualBox 4.3.8 instead of the latest (4.3.10) as there is an issue with shared folders and the Guest Additions for 4.3.10

Setting up your project

First thing you’ll want to do is set up a directory for your new virtual machine. We’ll be creating an Ubuntu box for running Jenkins, the continuous integration server, so we’ll name it ubuntu-ci:

$ mkdir ubuntu-ci
$ cd ubuntu-ci

Next, create a Gemfile to manage your Ruby dependencies by doing the following:

$ bundle init

Then edit your Gemfile and add the following dependencies:

gem 'puppet'
gem 'librarian-puppet'

Now use Bundler to install the dependencies:

$ bundle

We’ll be using librarian-puppet to manage our Puppet dependencies. The puppet gem makes Puppet commands available to Vagrant.

Create the Vagrant project file

Next you want to create a Vagrant project file that describes and configures your VM.

We’re going to use the hashicorp/precise32 box as our base, which is a simple 32-bit Ubuntu box that has Puppet installed. You can find other base boxes using Vagrant Cloud.

$ vagrant init hashicorp/precise32

This creates a Vagrantfile in the current directory. For now we don’t care about its contents.

You can start up the VM with:

$ vagrant up

Once that’s done you should be able to ssh to the box:

$ vagrant ssh

Currently there isn’t much we can do with the box so let’s use Puppet to install something useful, like Jenkins, a continuous integration server.

Be sure to exit out of your SSH session first!

Managing Puppet Dependencies

Puppet is great for automatically provisioning machines – installing services, creating users, populating files, etc. This can be done by creating modules and manifests files that describe the resources you want on a machine. It’s very powerful but can also be overwhelming if you’re in a hurry to get up and running.

Fortunately a lot of this work has already been done for you and can be found on the Puppet Forge. We’re going to leverage an existing module that sets up Jenkins for us. We’re also going to use librarian-puppet to define and automatically install the module and its dependencies.

First, create a Puppetfile to define which Puppet modules you’ll be using with the following command:

$ librarian-puppet init

Then edit the Puppetfile to contain just the following:

#!/usr/bin/env ruby

forge "http://forge.puppetlabs.com"

mod 'rtyler/jenkins'

You can then install your Puppet dependencies by running:

$ librarian-puppet install

This will create a modules directory and populate it with the Jenkins module and any of its dependencies.

Now to tell Vagrant to use Puppet.

Set up Vagrant to use Puppet

Start by editing your Vagrantfile and adding the following inside the main Vagrant.configure block:

config.vm.provision "puppet" do |puppet|
    puppet.manifests_path = "manifests"
    puppet.manifest_file  = "site.pp"
    puppet.module_path = ['modules']

config.vm.network "forwarded_port", guest: 8080, host: 8042

The first section tells Vagrant that we want to use Puppet to provision our machine, that the manifest file is in manifests/site.pp and that modules are stored in the modules directory.

The last line tells Vagrant to forward any requests locally on port 8042 to port 8080 on the VM so we can access Jenkins via with our browser.

Next, create the manifest directory for Puppet:

$ mkdir manifests

And create the manifest file itself:

$ touch manifests/site.pp

Now edit manifests/site.pp to contain the following:

include ::apt
include jenkins

Tell Vagrant to reload so that your provisioning config is set up:

$ vagrant reload

And then finally provision the machine:

$ vagrant provision

You should now be able to access Jenkins via http://localhost:8042/.

You can continue to add and configure services by finding them on the Puppet Forge, adding them to your Puppetfile, instantiating/configuring them in your manifests/site.pp and then running vagrant provision.

Sample code from the above can be seen here: https://github.com/spilth/spinning-useful-vms-quickly-vagrant-puppet-puppet-forge


About the Author


Pivotal People—Janne Valkealahti , Spring YARN Master and Open Source Software Engineer
Pivotal People—Janne Valkealahti , Spring YARN Master and Open Source Software Engineer

Spring YARN is possibly one of the coolest projects on planet earth these days. Come meet Janne Valkealahti...

HOWTO: Spring XD for Real Time Analytics With Twitter Example Code
HOWTO: Spring XD for Real Time Analytics With Twitter Example Code

Spring XD is a unified, distributed, and extensible system for data ingestion, real time analytics, batch p...