Web Applications Are a Breeze with Chef

Just about everyone who works at Opscode comes from a heavy web operations background. Those who work in webops know that getting an Apache server configured and ready to run applications with various languages and frameworks can be a difficult task. Not only do we have a plethora of languages

The Chef

to choose from, there's a variety of frameworks within each of those, and they all bring their own Apache configuration directives. Chef makes it easier to configure servers consistently in general, and now a new recipe in the Opscode Chef cookbook makes it easier to deploy application configuration as well.

Whether you're running PHP (or Drupal), Python (er, Django) or Ruby (that is, Rails), you can use the new Apache 'web_app' define to deploy a new application-site vhost configuration template, then kick back with a latté and watch your server logs. Lets take a look at the actual configuration. We'll use a simple Rails example. Note that we're using Passenger to provide "mod_rails", with the Passenger cookbook that Mike Hale and Joshua Sierles wrote.

To get started, we first update to the latest Opscode cookbooks from github. In particular, the Apache2, Passenger and Rails cookbooks are needed. Assuming a local clone of opscode/cookbooks in ~/chef-repo/cookbooks (from using Working With Git wiki doc):

  git pull –rebase

Next we create a new Rails project in /srv/myproj. We're sure you'll want to deploy your app, though.

 cd /srv
 sudo rails myproj

Test that it runs with /srv/myproj/script/server and pointed our browser at http://hostname:3000/. Use 'hostname' instead of the 'fqdn' because we're still testing. Now we need to configure Apache+Passenger with Chef. From our local chef-repo, we have a site-cookbook, myproj.

 cat ~/chef-repo/site-cookbooks/myproj/recipes/default.rb
 include_recipe "rails"
 include_recipe "passenger"

 web_app "myproj" do
   docroot "/srv/myproj/public"
   template "myproj.conf.erb"
   server_name node[:fqdn]
   server_aliases [node[:hostname], "myproj"]
   rails_env "production"

Now we need the Apache vhost template, myproj.conf.erb, which is, for example:

 cat ~/chef-repo/site-cookbooks/myproj/templates/default/myproj.conf.erb
 <VirtualHost *:80>
   ServerName <%= @params[:server_name] %>
   ServerAlias <% @params[:server_aliases].each do |a| %><%= "#{a}" %> <% end %>
   DocumentRoot <%= @params[:docroot] %>

   RailsBaseURI /
   RailsEnv <%= @params[:rails_env] %>
   RailsAllowModRewrite on
   PassengerMaxPoolSize <%= @node[:rails][:max_pool_size] %>

   <Directory <%= @params[:docroot] %>>
     Options FollowSymLinks
     AllowOverride None
     Order allow,deny
     Allow from all

   LogLevel info
   ErrorLog <%= @node[:apache][:log_dir] %>/<%= @params[:name] %>-error.log
   CustomLog <%= @node[:apache][:log_dir] %>/<%= @params[:name] %>-access.log combined

After running rake install[1], Chef is ready! Add the myproj recipe to the node in the chef-server webui, and run the client:

 sudo chef-client
 [… copious output from chef configuring everything snipped …]

Then, point the web browser at http://hostname/ and the Rails app is available! (note lack of port :3000). Or, if you've updated your DNS settings, you can go to http://fqdn/.

So how does this work? Quite simply, the web_app define copies the template via Chef's template resource. It then calls apache_site to enable the site in the Apache configuration. Because definitions in Chef don't prototype all the parameters (none by default, in fact), you can pass any arbitrary parameters you want to use. Then, in the web_app define, these are copied to the template via the variables attribute:

 variables :params => params

Each param in the example for myproj above is available as @param[:parameter_name], as seen in the template.

The web_app definition can be used for other web application frameworks as well. Just pass parameters to web_app, and you can use them in your template. For more information about this, see README.rdoc in the Apache cookbook.

[1] This assumes you have a Rakefile with an install task that will put your cookbooks and site-cookbooks into a location for your server to use.

Joshua Timberman

Joshua Timberman is a Code Cleric at CHEF, where he Cures Technical Debt Wounds for 1d8+5 lines of code, casts Protection from Yaks, and otherwise helps continuously improve internal technical process.