Step 2.3: Implement a Custom Cookbook
Although a stack is basically a container for instances, you don't add instances directly to a stack. You add one or more layers, each of which represents a group of related instances, and then add instances to the layers.
A layer is basically a blueprint that AWS OpsWorks Stacks uses to create a set of Amazon EC2 instances with the same configuration. An instance starts with a base version of the operating system, and the instance's layer performs a variety of tasks on the instance to implement that blueprint, which can include:
Creating directories and files
Installing and configuring software
Starting or stopping servers
Deploying application code and related files.
A layer performs tasks on instances by running Chef recipes—recipes for short. A recipe is a Ruby application that uses Chef's domain-specific language (DSL) to describe the final state of the instance. With AWS OpsWorks Stacks, each recipe is usually assigned to one of the layer's lifecycle events: Setup, Configuration, Deploy, Undeploy, and Shutdown. When a lifecycle event occurs on an instance, AWS OpsWorks Stacks runs the event's recipes to perform the appropriate tasks. For example, the Setup event occurs after an instance finishes booting. AWS OpsWorks Stacks then runs the Setup recipes, which typically perform tasks such as installing and configuring server software and starting related services.
AWS OpsWorks Stacks provides each layer with a set of built-in recipes that perform standard tasks. You can extend a layer's functionality by implementing custom recipes to perform additional tasks and assigning them to the layer's lifecycle events. Windows stacks support custom layers, which have a minimal set of recipes that perform only a few basic tasks. To add functionality to your Windows instances, you must implement custom recipes to install software, deploy applications, and so on. This topic describes how to create a simple custom layer to support IIS instances.
A Quick Introduction to Cookbooks and Recipes
A recipe defines one or more aspects of an instance's expected state: what directories it should have, what software packages should be installed, what apps should be deployed, and so on. Recipes are packaged in a cookbook, which typically contains one or more related recipes, plus associated files such as templates for creating configuration files.
This topic is a very basic introduction to recipes, just enough to show you how to implement a cookbook to support a simple custom IIS layer. For a more general introduction to cookbooks, see Cookbooks and Recipes. For a detailed tutorial introduction to implementing cookbooks, including some Windows-specific topics, see Cookbooks 101.
Chef recipes are technically Ruby applications, but most, if not all, of the
code is in the Chef DSL. The DSL consists largely of a set of
resources, which you can use to declaratively specify
an aspect of the instances state. For example, a
directory resource defines a directory to be added
to the system. The following example defines a
directory with full-control rights that belongs to the specified user and does
not inherit rights from the parent directory.
directory 'C:\data' do rights :full_control, 'WORKGROUP\
username' inherits false action :create end
When Chef runs a recipe, it executes each resource by passing the data to an associated provider, a Ruby object that handles the details of modifying the instance state. In this case, the provider creates a new directory with the specified configuration.
The custom cookbook for the custom IIS layer must perform the following tasks:
Install the IIS feature and start the service.
You typically perform this task during setup, right after the instance finished booting.
Deploy an app to the instance, a simple HTML page for this example.
You typically perform this task during setup. However, apps usually need to be updated regularly, so you also need to deploy updates while the instance is online.
You could have a single recipe perform all of these tasks. However, the preferred approach is to have separate recipes for setup and deployment tasks. That way, you can deploy app updates at any time without also running setup code. The following describes how to set up a cookbook to support a custom IIS layer. Subsequent topics will show how to implement the recipes.
To get started
Create a directory named
iis-cookbookin a convenient location on your workstation.
metadata.rbfile with the following content to
name "iis-cookbook" version "0.1.0"
This example uses a minimal
metadata.rb. For more information on how you can use this file, see metadata.rb.
This directory, which must be named
recipes, contains the cookbook's recipes.
In general, cookbooks can contain a variety of other directories. For example,
if a recipe uses a template to create a configuration file, the template usually
goes in the
templates\default directory. The cookbook for
this example consists entirely of recipes, so it needs no other directories.
Also, this example uses a single cookbook, but you can use as many as you need;
multiple cookbooks are often preferable for complex projects. For example, you
could have separate cookbooks for setup and deployment tasks. For more cookbook
examples, see Cookbooks and Recipes.
Implement a Recipe to Install and Start IIS
IIS is a Windows feature, one of a set of optional system components that you can install on Windows Server. You can have a recipe install IIS in either of the following ways:
By using the Chef windows cookbook's
windowscookbook contains a set of resources whose underlying providers use Deployment Image Servicing and Management to perform a variety of tasks on Windows instances, including feature installation.
powershell_script is among the most useful resources for
Windows recipes. You can use it to perform a wide variety of tasks on an
instance by running the appropriate Windows PowerShell script. It's especially
useful for tasks that aren't supported by a Chef resource.
This example uses a Windows PowerShell script to install and start IIS. The
windows cookbook is described later. For an example of how to
windows_feature to install IIS, see Installing a Windows
Add a recipe named
install.rb with the following contents
to the cookbook's
powershell_script 'Install IIS' do code 'Add-WindowsFeature Web-Server' not_if "(Get-WindowsFeature -Name Web-Server).Installed" end service 'w3svc' do action [:start, :enable] end
The recipe contains two resources.
powershell_scriptruns the specified Windows PowerShell script. The example has the following attribute settings:
code– The Windows PowerShell cmdlets to be run.
This example runs a single
Add-WindowsFeaturecmdlet, which installs IIS. In general, the
codeattribute can have any number of lines, so you can run as many cmdlets as you need.
not-if– A guard attribute that ensures that the recipe installs IIS only if it has not yet been installed.
You generally want recipes to be idempotent, so they do not waste time performing the same task more than once.
Every resource has an action, which specifies the action the provider is to take. There is no explicit action for this example, so the provider takes the default
:runaction, which runs the specified Windows PowerShell script. For more information, see Running a Windows PowerShell Script.
servicemanages a service, the IIS service (W3SVC) in this case. The example uses default attributes and specifies two actions,
:enable, which start and enable IIS.
If you want to install software that uses a package installer, such as
MSI, you can use a
windows_package resource. For more
information, see Installing a
Enable the Custom Cookbook
AWS OpsWorks Stacks runs recipes from a local cache on each instance. To run your custom recipes, you must do the following:
Put the cookbook in a remote repository.
AWS OpsWorks Stacks downloads the cookbooks from this repository to each instance's local cache.
Edit the stack to enable custom cookbooks.
Custom cookbooks are disabled by default, so you must enable custom cookbooks for the stack and provide the repository URL and related information.
AWS OpsWorks Stacks supports S3 archives and Git repositories for custom cookbooks; this example uses an S3 archive. For more information, see Cookbook Repositories.
To use an S3 archive
.ziparchive of the
AWS OpsWorks Stacks also supports
.tgz(gzip compressed tar) archives for Windows stacks.
Upload the archive to an S3 bucket in the US Standard (us-east-1) region and make the file public. You can also use private S3 archives, but public archives are sufficient for this example and somewhat simpler to work with.
To upload the archive to an S3 bucket
Sign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/.
If you do not already have a bucket in us-east-1, click Create Bucket and create a bucket in the US Standard region.
In the buckets list, click the name of bucket to which you want to upload the file, and then click Upload.
Choose Add Files.
Select the archive file that you will upload, and then click Open.
At the bottom of the Upload - Select Files and Folders dialog, choose Set Details.
At the bottom of the Set Details dialog, choose Set Permissions.
In the Set Permissions dialog, choose Make everything public.
At the bottom of the Set Permissions dialog, choose Start Upload. When the upload finishes, the
iis-cookbook.zipfile will appear in your bucket.
Select the bucket in the bucket list, and then choose the Properties tab for the bucket. Next to Link, record the archive file's URL for later use. It should look something like
For more information about uploading files to an Amazon S3 bucket, see Uploading Objects into Amazon S3.
Up to this point, the walkthrough has cost you only a little time; the AWS OpsWorks Stacks service itself is free. However, you must pay for any AWS resources that you use, such as Amazon S3 storage. As soon as you upload the archive you begin incurring charges. For more information, see AWS Pricing.
To enable custom cookbooks for the stack
In the AWS OpsWorks Stacks console, choose Stack in the navigation pane, and then choose Stack Settings on the upper right.
On the upper right of the Settings page, choose Edit.
On the Settings page, set Use custom Chef cookbooks to Yes and enter the following information:
Repository type – S3 Archive.
Repository URL – The S3 URL of the cookbook archive file that you recorded earlier.
Choose Save to update the stack configuration.
AWS OpsWorks Stacks will now install your custom cookbook on all new instances. Note that AWS OpsWorks Stacks does not automatically install or update custom cookbooks on online instances. You can do that manually, as described later.