Bootstrapping Chef on Ubuntu 12 with Opscode Knife

Thursday, May 10, 2012

I enjoy using Opscode Chef since bringing up an automatically configured instance is fast and easy on any of our cloud providers.  Ubuntu 12 having just been released, I took the opportunity to perform QA testing on it as well as verify that our cookbooks would work as expected.  Using an Amazon EC2 published Ubuntu 12 AMI, I ran the "knife ec2 server create" command to create the instance and install our software.

Unfortunately knife complained of a few errors, and the instance itself did not end up having chef installed - the default knife bootstrapping commands were not modified yet to be compatible with the new release.  With Knife however, you can conveniently create custom bootstrap templates in case of issues like these.  Since Opscode provides an up-to-date apt repo that includes a chef package for Ubuntu 12, I modified the knife template to pull the correct packages, automatically installing them during the bootstrapping process.

To make a long story short, all that needs to be done is to modify the existing template for Ubuntu 10.04, and then modifying one of the lines of code to reflect the Ubuntu 12/precise apt repository, as show below.

[ -f /etc/apt/sources.list.d/opscode.list ] || echo "deb http://apt.opscode.com precise-0.10 main" > /etc/apt/sources.list.d/opscode.list

To add the custom bootstrapper, download the provided ubuntu12-apt.erb template below to your chef config bootstrap directory, e.g. ~/.chef/bootstrap/.  Then tell knife to explicitly use this bootstrap file by using the "-d" command, e.g.:

knife ec2 server create -d ubuntu12-apt -x ubuntu -I ami-c66acfaf -f m1.small -i mypem.pem -Z us-east-1a -A "access_key_id" -K "secret_access_key"

After executing the knife ec2 server create command, I had my instance up and running, with all my custom packages configured and ready to go.  Very convenient!

Here is the full Ubuntu 12 chef bootstrap template code, for your reference.

bash -c '
<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>

if [ ! -f /usr/bin/chef-client ]; then
  echo "chef	chef/chef_server_url	string	<%= @chef_config[:chef_server_url] %>" | debconf-set-selections
  [ -f /etc/apt/sources.list.d/opscode.list ] || echo "deb http://apt.opscode.com precise-0.10 main" > /etc/apt/sources.list.d/opscode.list
  wget <%= "--proxy=on " if knife_config[:bootstrap_proxy] %>-O- http://apt.opscode.com/packages@opscode.com.gpg.key | apt-key add -
fi
apt-get update
apt-get install -y chef

(
cat <<'EOP'
<%= validation_key %>
EOP
) > /tmp/validation.pem
awk NF /tmp/validation.pem > /etc/chef/validation.pem
rm /tmp/validation.pem

<% if @chef_config[:encrypted_data_bag_secret] -%>
(
cat <<'EOP'
<%= encrypted_data_bag_secret %>
EOP
) > /tmp/encrypted_data_bag_secret
awk NF /tmp/encrypted_data_bag_secret > /etc/chef/encrypted_data_bag_secret
rm /tmp/encrypted_data_bag_secret
<% end -%>

<% unless @chef_config[:validation_client_name] == "chef-validator" -%>
[  `grep -qx "validation_client_name \"<%= @chef_config[:validation_client_name] %>\"" /etc/chef/client.rb` ] || echo "validation_client_name \"<%= @chef_config[:validation_client_name] %>\"" >> /etc/chef/client.rb
<% end -%>

<% if @config[:chef_node_name] %>
[ `grep -qx "node_name \"<%= @config[:chef_node_name] %>\"" /etc/chef/client.rb` ] || echo "node_name \"<%= @config[:chef_node_name] %>\"" >> /etc/chef/client.rb
<% end -%>

<% if knife_config[:bootstrap_proxy] %>
echo 'http_proxy  "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
echo 'https_proxy "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
<% end -%>

(
cat <<'EOP'
<%= { "run_list" => @run_list }.to_json %>
EOP
) > /etc/chef/first-boot.json

<%= start_chef %>'
Top