Building a Django App Server with Chef: Part 1¶

Alternate title: Fucking Chef, How does it work?

When I started looking at Chef, I found it incredibly complex and lacking in fundamental documentation. This is going to be my experience understanding Chef while setting up a single server. This strategy can be used across multiple servers, with a little tweaking.

I’d like to thank Jacob for the ideas and some of the inspiration behind the code and ideas. The code for this blog post can be found on github. It will be expanded as I write updates.

Today’s code will be using tag blog-post-1 in the repo.

Goal¶ I’m hoping to write a blog series that goes from explaining what Chef is, to having a working Django server, and to release all this code so that you can tweak and use it with your own servers. I’ll be doing this to set up a new and configuration managed server for ReadTheDocs. There are a couple of other good chef intros available. However, they only get you to the super basic first step of setting up the server. Hopefully this series will be more in depth and useful to actually getting a real server running under Chef.

Basic terminology¶ Chef has some basic terminology that you need to understand before we get into things. I’m going to purposefully leave out a ton of stuff, because it isn’t really important for me now. Cookbook (cookbooks/*) A cookbook, not surprisingly, contains recipes. With my configuration, we’re only going to use one cookbook, that has multiple recipes. This is probably wrong and horrible, but it’s simple, which is the goal for now. Recipe (cookbooks/*/recipes/*.rb) A recipe is the basic building block of Chef. It is what does the meat of the work that you want done. Resources A resources is an abstraction that defines a specific piece of your configuration. It can be a file, a user, or just about anything you want to talk about on your system. Attributes (node.json) Attributes are just a blob of JSON that Chef uses to pass around data. It will be (slightly) different for each server that you want to set up. I really like this approach, because I think a data-driven approach is the correct way to solve this problem.

Bootstrapping chef¶ We’ll be running what is called chef solo. This means that chef will be run independently of a server, and just execute on our one host. This seems to be the easiest way to get things running. When you first run chef-solo , it will look for a solo.rb file. The documentation about configuring chef-solo does a decent job of explaining this. By default it looks in /etc/chef/solo.rb, so lets go ahead and use that. It has 2 required fields, a cookbook_path and json_attribs . cookbook_path tells chef where to find the “cookbooks” it uses to run your code, and json_attribs tells it where to load in your data dictionary. Note: The docs say that file_cache_path is required, but it just defaults to /var/chef/cache . For simplicity, we’re going to keep our cookbooks and json data file in /etc/chef . On my local machine I keep everything in a ~/projects/chef directory, and then sync that to the remote box. In production you’ll probably want to set up your remote server to pull from a repository somewhere, so that you can have a stable deployment base, but again, syncing from the local filesystem is simple and works.