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:
- VirtualBox to run your VMs
- Vagrant to automatically configure VMs
- Ruby to run the Ruby-based tools you’ll be using
- 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
$ 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:
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
config.vm.provision "puppet" do |puppet| puppet.manifests_path = "manifests" puppet.manifest_file = "site.pp" puppet.module_path = ['modules'] end 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
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
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
Sample code from the above can be seen here: https://github.com/spilth/spinning-useful-vms-quickly-vagrant-puppet-puppet-forge