Have you ever setup a Rails production environment from scratch, by hand? If you had, I share your pain every time when a new project started.
The process is often repetitive. To me, it seems to be a waste to do it manually every time. It also consumes time and attention. It would be great if I could spend them on tasks that bring more values to clients.
To minimize such waste, I have written two Chef cookbooks to automate the process:
- rackbox - to provision rack-based web server (Nginx as front server, Unicorn and Passenger as upstream app servers,
rbenvas ruby version manager).
- databox - to provision database server (supports MySQL and PostgreSQL).
In this post, I will show you a step-by-step guide on how to use the
cookbooks together with
knife-solo to provision a
remote server in 4 steps:
- setup Chef Solo environment
- modify config file
- provision remote server
- tweak Capistrano
A working example in also available at teohm/kitchen-example.
1. Setup Chef Solo environment
- Install Chef Solo tools on local machine.
- Download Chef cookbooks to local machine.
chef-soloon remote server.
Install Chef Solo tools
Let’s create a new directory,
1 2 3 4
knife-solo >= 0.3 as it includes a few major fixes and
Now, install the ruby gems.
Finally, setup a kitchen directory structure with
Download Chef cookbooks
I use Berkshelf to manage cookbooks. So we need a
1 2 3 4 5
(I added a hack here to force
berkshelf to use
runit 1.1.2 required
rackbox. Still looking for a better solution.)
We can now download cookbooks with
chef-solo on remote server
In this example,
testbox is a host I setup in my
1 2 3 4
2. Customize config file
- Download config example
- Customize config file
Download config example
Modify config file (JSON)
The config file starts with a
run_list. You specify a list of cookbook
recipes here. Chef will run them in the same order in this list.
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 31 32 33 34 35 36 37 38 39 40 41
3. Provision remote server
It uploads the kitchen directory and runs
chef-solo on the remote
server. Chef-solo will then takeover and execute the run list to setup
What do we get at this point?
Basically, it’s done!
We have a full-stack, rack-based server with:
- 3 user accounts (deploy, devops, apps)
rbenvas ruby version manager
passenger-standaloneas upstream app servers, managed by
mysqlinstalled and databases created
- all apps will be stored in
4. Tweak Capistrano deploy.rb
Now, it’s ready to deploy a Rack-based app to the remote server!
I have two example Rails apps available on Github:
There are a few minor tweaks required in Capistrano
deploy.rb, as listed below.
rbenv in Capistrano
Run bundler with
1 2 3
Restart app with
1 2 3 4 5 6 7 8 9 10 11
If you are interested on using the cookbooks, or have an idea/feedback/question about this topic, feel free to drop me (@teohm) a message. Pull requests and issue reports are definitely welcomed!