Image for post
Image for post

Vagrant Provisioning with Chef

Provisioning Systems with Vagrant and Chef-Zero

This is small tutorial on using Vagrant to provision a system using the Chef, popular change configuration platform released in 2009 that uses Ruby scripts called recipes to configure the state of a system. Recipes can be packaged into modular components called cookbooks.


Vagrant and Virtualbox are required for this to this tutorial, and ChefDK is recommended but not required. The tutorial examples use Curl and Bash, so if you use something alternative, let’s say PowerShell, you’ll have to convert any commands to the equivalent in PowerShell commands.

Image for post
Image for post

Windows 8.1

Using Chocolatey to install the requirements:

macOS High Sierra 10.3

Using Homebrew to install the requirements:

Fedora 28

Using native package manager Dandified YUM, or in short DNF, to install requirements:

Part I: Cookbook with Intelligent Defaults

In first part of this tutorial, we’ll using Vagrant’s Chef-Zero provisioner to apply a small cookbook that has some baked in intelligent defaults for running on Ubuntu 16.04 (Xenial Xerus).

Staging Work Area Structure

First let’s create a common work area for this tutorial. In bash, we can run this to create the initial structure:

mkdir -p ~/vagrant-chef/{cookbooks,nodes}
touch ~/vagrant-chef/Vagrantfile
cd ~/vagrant-chef/cookbooks
chef generate cookbook hello_web
chef generate attribute hello_web default
chef generate file hello_web index.html
mkdir -p hello_web/{attributes,files/default,recipes}
touch {attributes,recipes}/default.rb
cat <<-'HTML' > hello_web/files/default/index.html
<h1>Hello World!</h1>
├── Vagrantfile
├── cookbooks
│ └── hello_web
│ ├── attributes
│ │ └── default.rb
│ ├── files
│ │ └── default
│ │ └── index.html
│ └── recipes
│ └── default.rb
└── nodes
cd ~/vagrant-chef

Vagrant Configuration

As mentioned, in this we’ll use the chef-zero provisioner, which allows us to run recipes and cookbooks locally without the need for a full online Chef Server.

Vagrant.configure('2') do |config| = 'bento/ubuntu-16.04' 'forwarded_port', guest: 80, host: 8082

####### Provision #######
config.vm.provision 'chef_zero' do |chef|
chef.cookbooks_path = "cookbooks" # ❶
chef.add_recipe 'hello_web' # ❷
chef.nodes_path = 'nodes' # ❸
  1. Determine what cookbooks we want to run, which is hello_web.
  2. Specify a local directory that Chef Zero uses to create node json configuration files. These are stored in this directory, rather than on a Chef Server.
vagrant up --no-provision

Creating The Cookbook

Now we need to create the corresponding hello_web cookbook that will run a web server with our content on Ubuntu.

Image for post
Image for post
default['hello_web']['package'] = 'apache2'
default['hello_web']['service'] = 'apache2'
default['hello_web']['docroot'] = '/var/www/html'
apt_update 'Update the apt cache daily' do
frequency 86_400
action :periodic
package node['hello_web']['package']cookbook_file "#{node['hello_web']['docroot']}/index.html" do
source 'index.html'
action :create
service node['hello_web']['service'] do
supports status: true, restart: true, reload: true
action %i(enable start)

Provision the System

We can test this by simply running:

vagrant provision

Testing the Results

The results can be tested with curl:

curl -i
HTTP/1.1 200 OK
Date: Sat, 11 Aug 2018 02:46:57 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Fri, 10 Aug 2018 04:24:59 GMT
ETag: "3c-5730d207145f1"
Accept-Ranges: bytes
Content-Length: 60
Content-Type: text/html
<h1>Hello World!</h1>

Part II: Overriding those Intelligent Defaults

In the next part of the tutorial, we’re going to swap out Ubuntu 16.04 in favor of CentOS 7. As the intelligent defaults for Ubuntu won’t work for CentOS, we’ll have to override these.

Update the Vagrantfile

Let’s modify the Vagrantfile to use Cent OS and set alternative attributes:

Vagrant.configure('2') do |config| = 'bento/centos-7.5' 'forwarded_port', guest: 80, host: 8082
####### Provision #######
config.vm.provision 'chef_zero' do |chef|
chef.add_recipe 'hello_web'
chef.cookbooks_path = 'cookbooks'
chef.nodes_path = 'nodes'
#### Override Attributes ####
chef.json = {
'hello_web' => {
'package' => 'httpd',
'service' => 'httpd',
'docroot' => '/var/www/html'

Apply the new Vagrantfile

Let’s test the new Vagrantfile:

vagrant destroy --force # remove previous Ubuntu system
vagrant up

Test the Results

The results like before can be tested with curl:

curl -i
HTTP/1.1 200 OK
Date: Sat, 11 Aug 2018 04:05:43 GMT
Server: Apache/2.4.6 (CentOS)
Last-Modified: Sat, 11 Aug 2018 04:05:15 GMT
ETag: "3c-57320f7b0c9af"
Accept-Ranges: bytes
Content-Length: 60
Content-Type: text/html; charset=UTF-8
<h1>Hello World!</h1>

Final Thoughts

There you have it, how to run some use Vagrant to prototype and develop cookbooks using Vagrant using Chef-Zero. We only touched on a basic cookbook, but there’s so much more we could do. Because Chef Zero is a full Chef Server, we could also test roles, environments, search, and data bags.


Chef Articles

Chef Docs

Vagrant References

Written by

Linux NinjaPants Automation Engineering Mutant — exploring DevOps, Kubernetes, CNI, IAC

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store