I’ve always thought that Vagrant’s one of the coolest things since sliced bread, and an absolute godsend for provisioning server and database boxes quickly and cleanly in order to avoid cluttering up my main machine with extraneous fluff and to avoid snowflake configurations during development. The only drawback I’ve encountered so far is that it has always seemed to be more suited for *Nix boxes only.

With some Googling, help from people smarter than me and much experimentation, I’ve managed to provision a Windows Server 2008 R2 box and this post will chronicle some of the trials and tribulations I’ve faced on this interesting journey.

First off, you’ll need a licensed copy of the Windows OS, of course (I used Windows Server 2008 R2). Next, install the vagrant-windows plugin. Setup your OS according to the “Creating a Base Box” section and package it using

vagrant package --base  --output 

With that, you’ll be done with the easy part and the more interesting stuff begins. We’ll aim to provision our Windows box by first bootstrapping the installation of Chocolatey, an amazing little piece of software that brings automated command line software installs to Windows. Think of it as brew for OS X or apt-get for *Nix machines. Once Chocolatey has been installed, we’ll use it to get JDK 7 and Puppet to our box. For a more complete example, we’ll then use Puppet to setup ant, Git and Maven before adding Jenkins manually via the command line. You can clone the entire setup needed to replicate this example (minus the box itself) from the repo at Github.

First, let’s take a look at this particular line from the Vagrantfile:

config.vm.provision :shell, :path => "setup_requirements.cmd"

This setup_requirements.cmd will execute remotely execute 2 powershell scripts to install .Net 4 and Chocolatey respectively. Much thanks to ferventcoder, the author of Chocolatey and from whom I got the scripts from. Although the latest version of Chocolatey will install .Net 4 if it doesn’t exist, it doesn’t work for me when installing remotely via powershell, hence the need for a .Net installation script beforehand.

Once that’s complete, we install the JDK and puppet via Chocolatey before we reach this next interesting line:

config.vm.provision :shell, inline: "puppet module install --force rismoney/chocolatey"

There’s 2 things to take note of here. This line installs the Chocolatey package provider for Puppet’s usage, and the –force makes this command idempotent as the provisioning process will fail if you call

vagrant provision

without this flag. The advantage of being able to use Chocolatey’s package provider in Puppet is that you can reuse all of Chocolatey’s package names in Puppet. For example, our Puppet file looks like this:

node 'default' {
  package { "maven" :
        ensure => "3.0.5",
        provider => 'chocolatey'
  }
  package { "apache.ant" :
        ensure => "latest",
        provider => 'chocolatey'
  }
  package { "git" :
        ensure => "latest",
        provider => 'chocolatey'
  }
}

where the package names correspond to cinst maven apache.ant git. At the point of writing, cinst maven doesn’t work as it’s pointing to the 3.0.4 package, which is currently 404 and will cause your provisioning process to halt (be it Puppet or Chocolatey), so we point it to version 3.0.5, which is available.

With that, we now have a basic Windows box up and running. In the next part, I’ll delve into setting up Jenkins on our box remotely using WinRM and WinRS. No SSH required!