Chef and Vagrant sitting in a tree

Chef and Vagrant - Getting started

These are tech notes from a hack session I had on the use of Chef solo.

Prerequisites

  • Ruby
  • Vagrant
  • Bundler

Get started

Make a Gemfile like so:

source 'https://rubygems.org'

gem 'knife-solo'
gem 'berkshelf'

Install the required gems with Bundler

bundle install

Start a Chef Solo project

Use knife to initialise the project, which creates some of the directories and files you will need.

knife solo init .

We’re using Berkshelf to access community cookbooks, so lets make the Berksfile as we want

source 'https://supermarket.chef.io'

metadata

cookbook 'nginx'

We’ll be making custom recipies, so lets create our own cookbook

knife cookbook create workplace --cookbook-path=site-cookbooks

We should create a metadata.rb in the root to tell Chef about our project

name             'chef-hack'
maintainer       'Workplace Systems ltd.'
maintainer_email 'info@workplacesystems.com'
license          'All rights reserved'
description      'Installs/Configures workplace applications'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.0.1'

depends 'nginx'

Prepare a machine

We need a Linux machine to provision. For this we have number of options

  • spin up a box in “the cloud”
  • install and network a phyical machine
  • configure a virtual machine (vagrant)

Vagrant

Vagrant is nice tool to setup virtual machines locally, so lets use it. First off lets grab an image, Ubuntu will do.

vagrant box add trusty64 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box
vagrant init trusty64

Create some JSON to tell Chef about our box nodes/192.168.33.10.json

{
  "run_list": [
    "nginx",
    "workplace"
  ]
}

When we ran vagrant init a Vagrantfile was created, lets customise that file so Vagrant brings the machine up as we want.

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "trusty64"
  config.vm.network "private_network", ip: "192.168.33.10"

  VAGRANT_JSON = JSON.parse(Pathname(__FILE__).dirname.join('nodes', '192.168.33.10.json').read)

  config.vm.provision :chef_solo do |chef|
     chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
     chef.roles_path = "roles"
     chef.data_bags_path = "data_bags"
     chef.provisioning_path = "/tmp/vagrant-chef"
     chef.run_list = VAGRANT_JSON.delete('run_list')
     chef.json = VAGRANT_JSON
  end
end

Nows let bring up the machine

vagrant up

Note

Below you will notice I reference a user and SSH key generated by vagrant, to discover these I ran

vagrant ssh-config

First Chef run

We should be ready to provision our vanilla Linux machine.

(note: if using vagrant, this is already done when you ran vagrant up)

First lets grab the cookbooks from Berkshelf

berks install

Now lets prepare the Linux machine

knife solo prepare -i ./.vagrant/machines/default/virtualbox/private_key vagrant@192.168.33.10

And finally, lets run the cookbooks to actually to the provisioning

knife solo cook -i ./.vagrant/machines/default/virtualbox/private_key vagrant@192.168.33.10

Subsequent Chef runs

Now all our ducks are in a row, we can make changes to recipes, nodes, etc. then just re-provision the machine like so

knife solo cook -i ./.vagrant/machines/default/virtualbox/private_key vagrant@192.168.33.10

If you introduced any more cookbooks from the super market you’ll need to run

berks install

Write a recipe

Now we have an machine to up and can cook upon it, it’s time to do a custom recipe.

As we are just hacking, lets just start by adding ruby code into site-cookbooks/workplace/recipes/default.rb, if we were clever we’d group different functions in different recipes allowing us to seperate the funtions into roles, but for now lets just add the the ‘default.rb’

execute "echo 'hello world' > /tmp/a_test_file.txt"

execute is one of Chef’s most basic methods, see Chef Docs for more

We’ve just created our 1st recipe, lets provison a server with it. (see above)