2. Cooking Perl with Chef: Hello World Tutorial Page 2
Step 1: Provision a virtual machine
Create a directory to hold your configuration management files. It's a good idea to keep files in such a
directory under version control using git or a similar program, so you'll see that in the example
commands. Here, we create it under $HOME. If you create it somewhere else, remember to adjust for
that later in the tutorial.
$ cd $HOME
$ mkdir hw-tutorial
$ cd hw-tutorial
$ git init
If you have not already downloaded a Vagrant virtual machine when you installed and tested Vagrant,
do so now1:
$ vagrant box add lucid32 http://files.vagrantup.com/lucid32.box
Create a Vagrant configuration file and commit it to the repo:
$ vagrant init lucid32
$ git add Vagrantfile
$ git commit -m "added Vagrantfile"
Open the Vagrant config file with your preferred editor, and edit the 'config.vm.forward_port' setting
that forwards local port 8080 to port 80 of the virtual machine. Uncomment it and change it to forward
8080 to 8080 so that later we'll be able to connect to the Hello World application on localhost port
8080.2 The resulting diff is shown below:
$ vim Vagrantfile
... edit the file ...
$ git diff
diff --git a/Vagrantfile b/Vagrantfile
index 840f77c..98b5e9a 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -29,7 +29,7 @@ Vagrant::Config.run do |config|
# Forward a port from the guest to the host, which allows for outside
# computers to access the VM, whereas host only networking does not.
- # config.vm.forward_port 80, 8080
+ config.vm.forward_port 8080, 8080
# Share an additional folder to the guest VM. The first argument is
# an identifier, the second is the path on the guest to mount the
1 This tutorial was written before Ubuntu Precise LTS was available as a Vagrant box. That box may work, but has not
been tested.
2 If port 8080 is already in use on your machine, use a different, available port number instead
3. Cooking Perl with Chef: Hello World Tutorial Page 3
Then commit that change, launch the Vagrant virtual machine, and check that you can log into it with
Vagrant's SSH command. After successfully connecting to the virtual machine, exit from ssh.
$ git commit -am "Enabled port forwarding"
$ vagrant up
... wait for it to boot ...
$ vagrant ssh
vagrant@lucid32:~$ exit
When Vagrant launches the machine, it will also create a .vagrant file that you'll probably want git to
ignore:
$ echo .vagrant > .gitignore
$ git add .gitignore && git commit -m "ignore .vagrant"
Congratulations! You have a virtual machine ready to configure.
Step 2: Prepare Pantry to manage Chef Solo
This tutorial uses Pantry and Chef Solo to configure the virtual machine and deploy the Hello World
application. Pantry manages your Chef configuration and deploys it to the virtual machine.3
Pantry will use SSH to communicate with your server, so you need to ensure that you can SSH to it
directly, without using the Vagrant command line. You'll do that by adding the Vagrant SSH private
key to your SSH agent and connecting to port 2222 (which Vagrant forwards to port 22 of the virtual
machine). Github users should read an important footnote.4
Once the connection succeeds, look around if you'd like and then exit out of ssh.
$ ssh-add ~/.vagrant.d/insecure_private_key
$ ssh vagrant@localhost -p 2222
vagrant@lucid32:~$ exit
Now you're ready to initialize Pantry:
$ pantry init
This will create several directories to hold your Chef configuration files and cookbooks.
3 If you know Vagrant well, you may wonder why we use Pantry instead of Chef Solo support built into Vagrant. Pantry
is a more general solution, and the techniques shown here apply exactly the same whether deploying to a local Vagrant
machine or to a remote physical or virtual server.
4 You'll want to use ssh-add to remove the Vagrant insecure key from the SSH agent when you're done with the tutorial or
Github will reject you as unauthorized, even if you also have a valid Github key. This is a bizarre failing in either ssh-
agent or Github's SSH server.
4. Cooking Perl with Chef: Hello World Tutorial Page 4
Next, use Pantry to create a JSON node file to hold the configuration for your virtual machine, and
commit that to your repository.
$ pantry create node vagrant --host localhost --port 2222 --user vagrant
$ git add environments
$ git commit -m "create node file for vagrant server"
These commands create the configuration for a node named "vagrant". Since Vagrant runs on
localhost, forwards SSH via port 2222, and the SSH key it provides is for the 'vagrant' user, we need to
be explicit with those parameters. For a "real" server, the node name would be the fully-qualified
domain name and you can omit those extra parameters. The default user name is 'root', and Pantry will
use sudo instead if you override that with a non-root user.
Good job! Now that Pantry is set up, you're ready to configure your node for Hello World.
Step 3. Get Hello World cookbook and dependencies
Chef implements configuration scripts and related data in the form of "cookbook" directories. For this
tutorial, you'll need four cookbooks:
• Hello World
• Perlbrew
• Carton
• Runit
These are available from various git repositories. You'll need to check them out into separate
directories and then copy the relevant files into the 'cookbooks' directory that Pantry created.
$ cd $HOME
$ mkdir cookbook-repos
$ cd cookbook-repos
$ git clone git://github.com/dagolden/zzz-hello-world.git
$ git clone git://github.com/dagolden/perl-chef.git
Note that the Perl Chef repository contains both the Perlbrew and Carton cookbooks.
The Runit cookbook is a little different — you need the CHEF-154 branch of my own Runit repository,
which addresses some particular bugs and hasn't yet been merged to the master Opscode branch. Plus,
the cookbook files are in the top level directory, so you have to omit the .git directory later when you
copy it.
$ git clone git://github.com/dagolden/runit.git -b CHEF-154
Let's take some time to examine the Hello World application and some of the files inside.
$ cd zzz-hello-world
$ ls
5. Cooking Perl with Chef: Hello World Tutorial Page 5
Notice the carton.lock file — this contains a frozen set of Perl module dependencies for use with the
Carton tool (c.f. https://metacpan.org/module/Carton). Notice also the app.psgi file — this is the web
application itself.
The cookbook directory contains the Chef cookbook for deploying this application with Chef. Look at
the metadata.rb file; it shows that this cookbook depends on the 'carton' cookbook, which is why we've
checked that out as well. (Carton, in turn, depends on Perlbrew and Runit.) Look at the README.md
file for some bare-bones description; note the list of default configuration attributes available. Those
can be modified for a given node using Pantry, as we'll see later in this tutorial.
$ cd cookbook/hello-world
$ more metadata.rb
$ more README.md
You'll probably want to examine the other files later to see how they work and how to adapt them for
your own needs, but for now, you'll want to copy the relevant cookbooks to your Pantry cookbook
directory. (Remember that we have to strip the .git directory from runit.)
$ cd $HOME/cookbook-repos
$ cp -a zzz-hello-world/cookbook/hello-world $HOME/hw-tutorial/cookbooks
$ cp -a perl-chef/cookbooks/carton $HOME/hw-tutorial/cookbooks
$ cp -a perl-chef/cookbooks/perlbrew $HOME/hw-tutorial/cookbooks
$ rsync -a --exclude=.git runit $HOME/hw-tutorial/cookbooks
Now that you've copied all the cookbooks to your Pantry, you should check them in to version control.
$ cd $HOME/hw-tutorial
$ git add cookbooks
$ git commit -m "added hello-world, carton, perlbrew, runit cookbooks"
Excellent! Now you're ready to configure the Vagrant node you created to use those cookbooks.
Step 4. Configure virtual machine for Hello World
There are two parts to configuring the Vagrant node with Pantry. First, you need to add the Hello
World recipe (from the Hello World cookbook) to the run-list for the node. Second, you need to
modify any configuration settings. In this case, rather than running the default Perl v5.16, let's run
under the previous stable version instead:
$ pantry apply node vagrant --recipe hello-world
$ pantry apply node vagrant --default hello-world.perl_version=perl-5.14.2
$ git commit -a -m "configured hello world on vagrant node"
You can see the resulting configuration with the 'show' command:
$ pantry show node vagrant
That's it! Your configuration is done.
6. Cooking Perl with Chef: Hello World Tutorial Page 6
Step 5. Deploy and test
To deploy the configuration to the node, run the 'sync' command:
$ pantry sync node vagrant
This first run will take a very long time because Chef Solo must compile a fresh copy of Perl in an
isolated directory under /opt, then install all the Hello World dependencies in an isolated local library as
well. Because Vagrant gives you a virtual machine with a single processor allocated and very little
RAM, this is slow!
So be patient, get a favorite beverage, have mock swordfights or whatever suits you, and wait until it's
done. If you're worried about progress, "vagrant ssh" into the server and tail the perlbrew build file
(you'll see instructions on screen about it).
Assuming there are no errors during the run, you should now be able to browse to localhost:8080 and
see a short web page from the Hello World application.
If it didn't work, check Appendix II for some troubleshooting tips.)
Congratulations! You did it!
If you'd like, log into the Vagrant box and look in /opt/perlbrew, /opt/hello-world and /etc/sv/hello-
world to see the files that were deployed.
Don't forget to shut down the vagrant box when you're done. Destroy it if you'd like to reclaim the
space it used.
$ vagrant halt
$ vagrant destroy
7. Cooking Perl with Chef: Hello World Tutorial Page 7
APPENDIX I: Preparing your own virtual machine
If you would like to use your own virtual machine or other server, you must ensure that Chef 10.4 or
higher is installed. You will either need a root user with SSH access or a non-root user with SSH
access that is authorized to run sudo. You will need to ensure that the firewall allows access to the SSH
port and to port 8080.
With the exception of creating a directory and initializing git, you can skip Step 1. In Step 2, modify
the "pantry create" command as appropriate for your server. For a root user and using the standard
SSH port, the "pantry create" command only needs the fully qualified hostname.
$ pantry create node server.example.net
As a nice convenience, Pantry lets you later refer to that node using any unique subset of the name (e.g.
"server"). You'll want to use that to refer to the node wherever a pantry command in the tutorial refers
to "vagrant".
APPENDIX II: Troubleshooting
I'm sorry that things aren't working for you. Your system might be too different than the one I used to
write this tutorial, in which case it might never work ☹. Or maybe you just missed step or a detail
along the way. Here are some things to check, based on problems I had when writing the tutorial:
• Check that you're running only one Vagrant box with 'vboxmanage list runningvms'
• Check that VirtualBox is forwarding the ports you expect (2222 and 8080) with 'sudo lsof -i'
• Check that your Vagrantfile is configured to forward port 8080 (local) to port 8080 (remote)
• Check that your Runit cookbook is from the CHEF-154 branch from the dagolden repository on
github
When I found problems, I found it easiest to start the tutorial over with a fresh Vagrant machine.
If those tips don't help you debug it, feel free to email me at xdg@xdg.me and tell me what's
happening. I can't promise a fix, but I do promise to read it and get back to you one way or another.
Check out http://perlchef.com/ for updates or additional resources.