John Goodall

Research Scientist

Cyber Resilience and Intelligence Division

Oak Ridge National Laboratory



Vagrant, Chef, and Berkshelf

Vagrant is a tool to create portable, sharable development and testing environments. It is used to build, provision, and configure a virtual machine (by default, VirtualBox). Here we will configure Vagrant with nodejs and redis. Chef and berkshelf are used for provisioning.

The complete setup is available at

Install and configure Vagrant

First, download VirtualBox and install.

Download a Vagrant installer for Mac OS, Windows, and Linux and install it.

To create an initial Vagrant file, run the command:

	vagrant init

The init command creates a sample Vagrantfile, which is the main configuration.

The first thing we need to do is add a box. Vagrant has a couple of preconfigured Ubuntu boxes (referred to in the Vagrant Docs), but there is a large list of available boxes. We are just going to use one of the available Ubuntu boxes, precise64 (Ubuntu 12.04). Edit the Vagrantfile, near the top:

# Every Vagrant virtual environment requires a box to build off of. = "precise64"

# The url from where the '' box will be fetched if it
# doesn't already exist on the user's system.
config.vm.box_url = ""

To access the guest VM from the host OS, set up port forwarding. To set forwarding to access port 8000 on the guest VM from http://localhost:8000 on the host OS: :forwarded_port, guest: 8000, host: 8000

For the VirtualBox provider, we can customize the provider settings by modifying this section, for example to set the VM memory to 2GB:

config.vm.provider :virtualbox do |vb|
  vb.customize ["modifyvm", :id, "--memory", "2048"]

Here is a full list of the settings for VirtualBox.

Configure provisioning

We will use Chef for provisioning, but Puppet works too. Ops people undoubtedly have a preference, but for our purposes either works. One of the main differences is that Chef configuration is written in Ruby, while Puppet uses its own domain specific language.



Chef Solo

While either Puppet or Chef will work, but we are going to use Chef Solo with our Vagrant setup. The Vagrant documentation on Chef Solo has more information.

First, let's update the packages already installed:

# Update the list of packages
config.vm.provision :shell, :inline => "sudo apt-get update -y"

This will not actually do the upgrades, for that you will need to run sudo apt-get upgrade -y, but grub seemed to be giving me errors when trying doing that automatically from the Vagrantfile.

You can download cookbooks into your Vagrant repository and configure in the Vagrantfile, or you can use one of the cookbook management tools, such as berkshelf:

gem install berkshelf

Create the file Berksfile and add the following:

cookbook "git"
cookbook "nodejs"
cookbook "redisio"

Add the following line to your Vagrantfile:

# Use [berkshelf](
config.berkshelf.enabled = true

Install nodejs, setting the version to the latest stable or what version you need, redis, and yeoman, node-supervisor, and http-server:

config.vm.provision :chef_solo do |chef|
  chef.json = {
    "nodejs" => {
      "version" => "0.10.7"


  chef.add_recipe "git"
  chef.add_recipe "nodejs"
  chef.add_recipe "redisio::install"
  chef.add_recipe "redisio::enable"


# install global node modules
config.vm.provision :shell, :inline => "npm install -g yo grunt-cli bower supervisor http-server"

Note, there are several cookbooks for node.js and redis; this uses the redisio and the nodejs cookbooks.


At this point, you probably want to install your own software. You can do this from your Vagrantfile using git, but then you will have to do a git pull after all your changes. Another approach is to clone everything inside your vagrant directory and it will then be mounted within the guest VM automatically. Anything that is in the same directory as the Vagrantfile will be mounted within the VM in /vagrant.

If you have multiple sub-projects, another approach is to put all of your sub-projects under one project-root directory. One way to configure things if you have multiple projects and a separate repo for your vagrant configuration is to set up your directory structure like this:

- project-root
  - vagrant-config
  - sub-project1
  - sub-project2

And then symlink your Vagrantfile to the project-root (ln -s vagrant-config/Vagrantfile .). Using this approach, you can edit your code in your host OS using Sublime Text, or whatever editor you like, and it is automatically changed in the /vagrant directory. Alternately, everything will be under your vagrant configuration repo.

To create the VM, run: vagrant up. This will take a few minutes as it downloads the box, configures the VM, updates install packages, and installs the packages listed in the Vagrantfile.

Redis should be running already (that is what the redisio::enable does). Because port forwarding for the redis port is configured, you can use redis-cli from the host OS to connect to the guest (assuming you don't also have redis running on the host).

If you have a nodejs process server set up and running on port 8000 (or if you have it set to start on a different port, change the mapping in the Vagrantfile), you can open a browser or use curl to access the server from the host OS by going to http://localhost:8000/

To log into the VM, from the directory that has your Vagrantfile, do: vagrant ssh. Here is a list of all Vagrant commands.