Cooking up some fresh Node recipes with Chef

If you haven't yet heard about Chef ("Infrastructure Automation for the Masses") then get out from under your rock! It is a neat tool for easily deploying servers with your desired configuration in a single command. In a nutshell, instead of configuring a server (yawn), you actually code your desired server configuration into something called a recipe. Once you have these recipes in order you can simply ask chef to spawn new servers for you. Chef will take care of everything, it will start your cloud servers, bootstrap them with your required packages and dependencies, deploy your applications and kick up your services. Chef also has cool names for everything, from the tool you use (knife) to the type of coding you are doing (devops), which not only helps make you feel like a l33t hax0r, but also turns configuring servers from being a massive pain into something that is almost fun (almost). Read past the break for more info...


Chef

Chef has loads of community created cookbooks (collections of recipes). However, being the cool nodelers we are we instantly noticed the gaping node hole on the Chef community pages. That is until we decided to give back and share our recipes for easily installing node, npm, and deploying node servers.

Chef Ramsay approves

Chef Ramsay approves?

In this article, we present both how to use our node recipes, as well as how the recipes came together. Hopefully people will be inspired to create their own recipes (it is actually pretty easy) and perhaps fellow Nodelers will also start to automate their own node installations.

What's a chef recipe?

A simple recipe is basically a set of instructions that need to be performed to have a desired program installed, configured and run. A more involved recipe will also expose providers, services that can be called in other recipes, using pre-defined actions. Recipes are parts of cookbooks and you can combine them to form more complex recipes that, for example, spawn a classic LAMP server (using the recipes for apache, php and mysql). At the end of the day, you will almost certainly have to create your own recipes to get things how you like them.

Our node recipe offers configurations for downloading, compiling and installing the node environment, as well as providers to start/stop node servers in your own recipes. Finally there are also convenient providers for installing/managing additional packages via npm (Node Package Manager).

Self Affirmation

Let's say you want to deploy a node server that helps you feel good about yourself. It will just return "You look great today! New haircut?" on every request.

This example will assume you have a running chef-client installation (if you don't, check the chef getting started guide) and already understand the basics of Chef and how to run roles on server nodes.

Let's get cooking

First, you need to get our node cookbook and add it to your own chef-repo. You can obtain it from the chef community site or from our github repo.

Now you'll need to create the new recipe for your own server, you can do so by running:

> knife cookbook create awesome-node
Next copy the following script into cookbook/awesome-node/files/default/awesome.js.

Excellent, now we're ready to write our own recipe. Let's edit the file cookbook/awesome-node/recipe/default.rb, then just copy/paste the following code:

The Chef Domain Specific Language makes understanding the server configuration simple. All we need to do now is add the recipe to the run list of our server, run the chef-client and... oh, that's it! At the end of the execution, you should have a running node server that cheers you up with "You look great today! New haircut?" on any request. This example also helpfully outputs your server log to /var/log/node-awesome-node.log.

The node_server provider in the above example will actually except the following parameters:

  • action: in {:start,:stop,:restart}, what should node server do (mandatory)
  • script: the script you want to run as a node server (mandatory)
  • user: the server will be started by this user
  • args: any arguments to pass to the server
  • dependency: a list of npm modules required by your script, they will be installed before starting the server (default: [])

How the node recipe works

Node installation

Chef actually made it very easy to design this node recipe:

The First line indicates that you need the git recipe; it is provided by Opscode, so you should be able to > knife cookbook site vendor git it to add it to your cookbook.

The following lines detail the installation of package, required for compiling node. For each of them, we use Chef's internal "package" provider with "action :install", (a syntax we copied for our node recipe). We also added some exceptions for the openssl package which differs according to the target distribution.

Then, we basically run the commands to download node from git (using the parameter "version" defined in cookbook/node/attributes/default.rb), compile it and install it, and we do the same for npm, basically following the instructions given on the respective node and npm github repos.

Node server and npm provider

But Chef can do better than that. As shown in the previous section, you can easily spawn a node server using what chef calls a provider. Here's how it works.

Basically, we defined the kind of action and attributes accepted by our provider, and their types. Note that the name used to invoke the provider is built on the name of the recipe (here : node) and the name of the provider (server), separated with underscores. Hence, the command called in the example of previous section, node_server.

Now we need to define in the file cookbook/node/providers/server.rb what to do with those actions and attributes (note: file names are important since Chef uses file naming conventions to work out which providers to use):

In the first block for action :install, we read the "dependency" attribute and install each node module one by one using npm. In the next block, we set up a new upstart configuration file (using chef's template system). Upstart is a system just like the classic unix init.d to manage daemons with the advantage of being almost human-friendly.

Finally, we invoke upstart with the start command and the newly created config file to start our node server!

Wait! There's more!

Remember that along with node, we also installed npm. Is is called internally with the "dependency" parameter of the node_server provider, but we also implemented a provider for npm, node_npm. Here's how to use it: This code will install module "module" as root. You can uninstall a module (action :uninstall), or perform the same operation as a standard user rather than root, with action :linstall and action :luninstall. Can it get simpler than that ?

You've been served

This node cookbook has just been release. Chef, Node and this recipe in particular are very new so we can't promise you won't come across some issues. Feedback and pull requests are more then welcome at the github repo. For now it has only been tested with ubuntu, but it should only require minor modification to work with other distributions. Hopefully you'll find this recipe helpful, even if it is a little buggy!

Acknowledgments

The script "awesome-node.js" is a trivial modification of the example provided on the node webpage. The template used for upstart has been designed following this tutorial.


Comments (0)


This thread has been closed from taking new comments.