Having recently started working with chef I have come up with a simple method of kickstarting use of it in the small end of town. This really is designed for those of use managing a large number of very similar servers, or a small number of simple servers.

After watching this great presentation on chef by @benr from joyent, I decided it was time to roll up my sleeves and get started with chef. To do this I took some of his advice and my meager Unix knowledge and crafted a simple bootstrap method for my development Ubuntu systems, which I will describe in this post.

Firstly I get myself an ubuntu development system which I use to build my develop the profile I will use for this system in the future. If this is done locally I grab the ubuntu install CD for the server version and follow the default installation options with the only service I install being openssh. If your using a VPS this is typically what you get out of the box.

Because I am doing this on a local server I normally use ssh-copy-id to copy over my ssh public key the easy mode way.

ssh-copy-id admin@ubuntuserver

Next I run my bootstrap script to install my environment on the server, note the link below is retrieving a specific revision based on the raw link in the gist this may change based on my updates.

ssh admin@ubuntuserver -t -C 'curl https://raw.github.com/gist/3328844/2f4d74d49f8f7a2cd0b7a83a23fafe75d21241cf/gistfile1.sh | sudo bash'

In the next few steps I export my chef-solo template project to the system and build up a recipe for producing this type of system. You may do this differently, I have a script with all these commands in it but I have exploded it for this example.

I start my dev cycle by generating a new ssh key pair and upload that to github or bitbucket depending which one you use.

ssh admin@ubuntuserver -t -C "ssh-keygen -t rsa -b 4096 && cat ~/.ssh/id_rsa.pub"

Make the chef directory and chown it for my admin user.

ssh admin@ubuntuserver -t -C "sudo su - -c '(mkdir /var/chef && chown admin:admin /var/chef)'"

Clone my git project whilst retaining ownership of the files by my admin user, for those new to git see the awesome git book.

ssh admin@ubuntuserver -t -C "git clone git@github.com:wolfeidau/chef-solo-base.git /var/chef"

Initialise the sub-modules and update them, this is something I always forget unless I have a script to follow..

ssh admin@ubuntuserver -t -C "cd /var/chef && git submodule init && git submodule update"

Now you can run chef-solo just to ensure it is all running as expected.

ssh admin@ubuntuserver -t -C 'sudo chef-solo -c /var/chef/solo.rb -j /var/chef/node.json'

This template is comprised of:

  • solo.rb - Glue code which loads various directories.
  • node.json - This is the dna for your system and will be available to your recipes as meta.
  • cookbooks - This directory holds the cookbooks. ** main - This cookbook is where my default recipe is located and all its associated templates. *** templates - This holds all my templates which I use to craft new or replacement configuration files. ** openssl - This is my first external cookbook, once I work out what I am doing I tend to externalise a few functions using other peoples cookbooks.

Using the handy tree command we can see the overall structure of the template.

markw@chefdev1204:/var/chef$ tree
.
├── cookbooks
│   ├── main
│   │   ├── recipes
│   │   │   └── default.rb
│   │   └── templates
│   │       └── default
│   │           ├── bambooxml.erb
│   │           ├── pg_hba_conf.erb
│   │           ├── screenrc.erb
│   │           ├── serverxml.erb
│   │           ├── tomcat7.erb
│   │           └── zshrc.erb
│   └── openssl
│       ├── CHANGELOG.md
│       ├── CONTRIBUTING
│       ├── libraries
│       │   └── secure_password.rb
│       ├── LICENSE
│       ├── metadata.rb
│       ├── README.md
│       └── recipes
│           └── default.rb
├── node.json
├── README.md
└── solo.rb

8 directories, 17 files

In my example I have commented out a whole section of example code which bootstraps my CI server using chef, this is gives me some starting points. Note that I am not an authority on either chef or ruby so my scrappy sysadmin code may make some people grimace but it is a starting point.

Once you’re ready to start hacking remove the remote repo and add your own.

git remote rm origin

Next some rules I try and live by when using chef:

  1. Keep it simple, if a recipe looks complicated or you don’t understand it don’t use it.
  2. Don’t use chef as an alternate package manager, make packages using fpm and install them.
  3. Please reread #1.

Most importantly get started with this tool you will never look back once you have a few systems built using it.

To add more recipes from opscode-cookbooks account simply navigate to the base of your project and run something like the following example.

git submodule add https://github.com/opscode-cookbooks/openssl.git cookbooks/openssl

Once I have completed my chef project I check it out on my workstation and use rsync to push it to a clean target host for testing.

Again I run ssh-copy-id to copy my ssh key.

ssh-copy-id admin@ubuntuserver

Bootstrap chef onto the server.

ssh admin@ubuntuserver -t -C 'curl https://raw.github.com/gist/3328844/2f4d74d49f8f7a2cd0b7a83a23fafe75d21241cf/gistfile1.sh | sudo bash'

Create my chef directory.

ssh admin@ubuntuserver -t -C "sudo su - -c '(mkdir /var/chef && chown admin:admin /var/chef)'"

Using rsync and a locally checked out repo copy the files to the remote machine.

rsync -axvr -e ssh my-chef-project/ admin@ubuntuserver:/var/chef/