AWS DevOps Blog

Customizing AWS OpsWorks with Attributes

There are a number of ways to customize Amazon EC2 instances using AWS OpsWorks. In a previous blog we demonstrated some easy ways to customize OpsWorks by writing your own recipes.

In this blog we’re going to show how to use Chef attributes to customize recipes. Chef attributes are input parameters to Chef recipes. The OpsWorks built-in cookbooks include a set of attributes that specify values such as the Apache server timeout. Sometimes you may not want to use the attribute values in the OpsWorks built-in cookbooks. In that case, you can override the built-in attribute and provide your own value. OpsWorks provides two ways to override built-in attributes: via custom JSON and via a custom cookbook attributes file.

Custom JSON is a convenient way to override the built-in cookbook attributes, but it has some limitations. In particular, you must enter custom JSON manually for each stack, so you have no robust way to manage the definitions. A better approach is often to use custom cookbook attributes files. Doing so allows you to place the definitions under source control.

There is an empty customize.rb file in each built-in cookbook that you can use to override specific attribute values without affecting other attributes. Just create a cookbook with the same name in your cookbook repository, add a customize.rb file to the cookbook’s attributes folder, and put your overridden attributes in that file.

Let’s look at the nginx attribute file in the OpsWorks built-in cookbooks. There are a number of attributes that you can override. If your server needs to accept large uploads, for example, you might want to modify the maximum body size, which is set by the following attribute definition:

default[:nginx][:client_max_body_size] = ‘4m’

To increase the maximum, add that attribute definition to nginx/attributes/customize.rb in your repository. To override the attribute, you must change the precedence level from default to a higher value, typically to “normal”:

normal[:nginx][:client_max_body_size] = ‘5m’

Once you have added this line to the nginx/attributes/customize.rb, add your repository’s URL to your OpsWorks stack, boot an instance, and the Nginx Setup recipes will automatically use your new attribute values to configure the server.

Sometimes your application requires secure attributes that you don’t want to check into your source repository. One option is to store that information in an S3 object. This allows you to separate responsibilities so that only certain users can access the secure data. To access the object from your OpsWorks instances,

  1. Go to the IAM console
  2. Select the instance role (the default is aws-opsworks-ec2-role)
  3. Select Attach Role Policy
  4. Select custom policy and add a policy such as:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:GetObject"
      ],
      "Sid": "Stmt0123456789",
      "Resource": [
        "arn:aws:s3:::<your-s3-bucket-name>/<your-object-name>"
      ],
      "Effect": "Allow"
    }
  ]
}

 

Then, add a Chef recipe to your repository to get your object on the instance’s Setup event, for example:

 

getS3.rb
require 'rubygems'
require 'aws-sdk'

s3 = AWS::S3.new
obj = s3.buckets['your-S3-bucket-name'].objects['your-object-name']
Chef::Log.info(obj.read)

 

You can then use the data retrieved from S3 to configure your application. If you find other settings you want to change in the OpsWorks cookbooks that are not available as attributes, please submit a pull request. For more information about customizing OpsWorks, including overriding templates and recipes, see the documentation.