We installed Chef Solo in part 1, we wrote some recipes in part 2, and now we’ll be tying everything together in part 3. When we’re done, we’ll not only have a fully provisioned server running your Rails app, but we’ll also have an automated way of repeating this process whenever such a need arises in the future.
Some Groundwork
Before we can run the recipes from part 2, we need to specify exactly which recipes we want to run and in what order. Chef has something called a run list exactly for this purpose, and we store it in the JSON file located in the /nodes
directory (I usually add it to the top of the file, before all the node-specific attributes, to make it easy to spot):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Because Chef executes the run list in the exact order it’s specified, it’s important to list the recipes that other recipes will depend on first. Some of our recipes, for example, use the user that’s created in users.rb
, so that’s why we place that recipe near the top, but recipes that don’t depend on any other recipes can be placed anywhere you want. (Note that when referencing the default.rb
recipe, it’s enough to just specify the name of the cookbook it’s located in, but in order to run the other recipes, it’s necessary to specify the cookbook, along with the recipe’s file name.)
By the way, if you ever find yourself not needing a particular recipe to run, all you need to do is remove that recipe from the run list, and Chef won’t run it, but do be careful about removing recipes that other recipes depend on because that will cause issues.
Show Time
With our run list defined, we’re now ready to start the provisioning process. Because we’ll need to use quite a number of commands to get everything provisioned, it’s best to automate this by creating a shell script. I created a file called setup_vps.sh
inside my app’s /config
directory for this purpose:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
The first line uploads your public key to the node (server) you’re about to provision. (If you don’t do this, Chef Solo will ask you to type your password for every command it runs.) The next line installs Chef on our node using the knife solo prepare
command, while the line after that uses knife solo cook
to execute our run list. When it finishes, our node will be fully provisioned.
The remaining three lines run the Capistrano recipes to deploy my app (if you’re not using Capistrano for deployment, feel free to remove them). The third to last line uploads the public key for the Chef-created user (so Capistrano can log in without a password), the next line runs the Capistrano recipes, and the last line restarts Nginx (so the uploaded Rails app is loaded in).
Once you run chmod +x setup_vps.sh
to make the file an executable, you can cd
into the directory containing the script and run it with
1
|
|
where bob
is the Chef-created user, 123.123.123.123
is the IP address of the node you just provisioned, and 12345
is its port. When the script finishes executing, you’ll have a fully provisioned server running your Rails app.
Capistrano Code
In the interest of completeness, here’s the Capistrano code I use to deploy my app. First up is my setup.rake
file containing the all
task that I’m referencing in setup_vps.sh
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
And here’s my deploy.rake
file containing the start
task that I’m calling in setup.rake
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Below are my deploy.rb
and production.rb
files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
1 2 3 4 |
|
I won’t be explaining the Capistrano code because that’s already covered in parts 5 and 6 of my “Deploying Rails Apps” series, so be sure to check that out if you’re new to Capistrano or just need some clarification. (It’s worth noting that Chef actually has a deploy
resource that’s modeled after Capistrano, but I didn’t have time to learn how to implement my existing Capistrano recipes with it. If you’re interested though, feel free to give it a try.)
I hope this gave you a taste of what Chef can do, although I only scratched the service of what’s possible. Chef is a complex tool that can be used to manage entire server infrastructures, and although it might be overkill for managing a single server, it’s still a useful tool to learn if you spend a significant amount of time doing server provisioning. It’s definitely an improvement over shell scripts because it keeps your code readable and organized. Ultimately though, each tool has its place, and it’s up to you to decide what best fits your particular need.
Stay hungry. Stay foolish.