Checkout My GitHub! Adam Codez

Getting started with Chef Solo and Knife Solo on Ubuntu

Adam Duke | 16 Nov 2015

We launched ZeroPush using Chef/Knife Solo and a kitchen based largely on this post. There were a lot of unanswered questions though. How do we safely store secrets? Should we really be running all this on one machine? How do we extract things to run on different machines? Over time we added things to the kitchen that made things easier, but why isn't there a canonical 'deploy my web app' kitchen out there? I've always wanted to go back and start over while applying what I've learned, to clean up the cruft. That's the goal of this series of posts.

Let's start by creating a totally vanilla kitchen.

$ mkdir webapp-kitchen && cd webapp-kitchen
$ cat > Gemfile << EOL
source 'https://rubygems.org'

gem 'berkshelf'
gem 'knife-solo'
EOL

$ bundle && bundle exec knife solo init .

Now that we have a kitchen, let's create a machine to run it on. Using Vagrant or your preferred cloud provider, provision a new machine using Ubuntu 14.04 and get the machine's ip. For the purpose of this post, I'm going to set that ip address as a shell variable so that if you're copying and pasting you only have to change it in one place.

$ KNIFE_SOLO_TARGET=<target ip address>
$ bundle exec knife solo prepare root@$KNIFE_SOLO_TARGET

The command above will create a file in the kitchen's nodes directory for our machine, and additionally install Chef on the machine. The generated node file should look something like:

$ cat nodes/$KNIFE_SOLO_TARGET.json
{
  "run_list": [
  ],
  "automatic": {
    "ipaddress": "<your-ip-here>"
  }
}

We can now actually run Chef on the machine by running:

$ bundle exec knife solo cook root@$KNIFE_SOLO_TARGET

That's progress, but doesn't really do much yet. Let's add a recipe to the node's runlist to see something actually happen. Edit your Berksfile to add the apt cookbook as a dependency and add the apt::default recipe to the node's runlist.

$ cat > Berksfile << EOL
source 'https://api.berkshelf.com'

cookbook 'apt'
EOL

$ cat > nodes/$KNIFE_SOLO_TARGET.json << EOL
{
  "run_list": [
    "apt::default"
  ],
  "automatic": {
    "ipaddress": "$KNIFE_SOLO_TARGET"
  }
}
EOL

Run Chef again.

bundle exec knife solo cook root@$KNIFE_SOLO_TARGET

At this point everything should be working. Running knife solo cook, against our machine, uploads the cookbooks to the server, generates some configuration files for Chef, and then starts the chef-client application using the newly generated configuration files and applies the apt::default recipe from the runlist.

In the next post, we'll secure the machine a bit by adding a firewall, adding a user for ourselves, giving our user sudo access, and a few other tweaks that we can share across all the nodes in our kitchen.