Deploying a Rails App to AWS OpsWorks using Chef 12

AWS OpsWorks is a configuration management service that uses Chef to automate server configurations. OpsWorks previously used Chef v11 and came with built-in cookbooks to deploy apps such as Rails, Node, and more. However, the latest OpsWorks Linux Chef v12 does not come with any built-in cookbooks. While this adds some more complexity to setting things up, it also comes with the added benefit of using community sourced cookbooks instead of ones developed by Amazon.

Our To-do List

Creating a Chef Cookbook

On your local machine, create a new cookbook:

chef generate cookbook "my-cookbook"
cd my-cookbook

Open up the freshly created Berksfile and metadata.rb in a text editor. We’re going to use the fantastic opsworks_ruby set of cookbooks to emulate what OpsWorks did for us on Chef 11, when all you needed to do was choose “Rails App” from a dropdown menu.

# Berksfile
source 'https://supermarket.chef.io'

cookbook 'opsworks_ruby', '1.4.0'
cookbook 'packages', '~> 1.0.0'
metadata
# metadata.rb
# -- ommitted metadata properties --

depends 'opsworks_ruby', '1.4.0'
depends 'packages', '~> 1.0.0'

We’re also using the packages cookbook that can install OS packages such as imagemagick, nodejs, or any other package your Rails app needs.

# recipes/default.rb

node.default['packages-cookbook'] = [
 'nodejs',
 'imagemagick'
]

Now we’re ready to package up these cookbooks and their dependencies. I recommend first installing the latest version of the Berkshelf gem, as I ran into some issues with the installed version from the Chef SDK.

gem install berkshelf
berks install
berks package cookbooks.tar.gz

You should now find cookbooks.tar.gz in your local directory; this archive contains all dependencies you’re included in your metadata.rb file, as well as all your dependencies’ dependencies. You’ll need to upload this file to an S3 bucket in your AWS account.

Creating a New OpsWorks Stack

create stack

Add your Rails App Layer

create layer

Layer Settings

Here we enter our custom JSON generated from opsworks_ruby’s handy configurator. I’m using Unicorn as my app server, an RDS endpoint for my MySQL database, and Ruby version 2.3. I’ve also configured it to not migrate the database for each deployment, as I’d prefer to do that manually. Additionally, I have assets_precompile disabled since I have that command running in a before_restart.rb hook instead of running it along with the recipes. For more custom attributes, visit the opsworks_ruby documentation.

general settings

Configure Layer Recipes from the opsworks_ruby recipes

create stack

Create and Deploy Your Rails App

Creating an app in OpsWorks is fairly self-explanatory, so I won’t go in detail about that here. Once you get your app set up, you’re ready to spin up a new instance of your choosing and deploy your Rails app.

Automating Packaging and Uploading Your Cookbooks to S3

I’ve created a tool to automate this process so you don’t have to pull up the S3 web interface or use the AWS CLI. You can download it here.

Fin

I have most likely left out some details in this rather brief post, but this should get you going pretty quickly. All remaining setup will probably be unique to your application.