Originally published on 2015-10-27; fully revised and updated.
This guide explains how to provision an AWS EC2 instance with the ChefDK-era chef-provisioning workflow. It is intended for teams maintaining older Chef automation and covers prerequisites, AWS credential setup, cookbook and Policyfile creation, and running chef provision safely.
Prerequisites and legacy context
The original process is based on older Chef tooling and patterns. Keep that in mind if your environment has moved to newer Chef workflows.
- Install ChefDK (original prerequisite link): tutorials/how-to-install-chefdk-in-rhel-ubantu-mac-and-windows
- Set up AWS credentials (original prerequisite link): tutorials/setup-aws-credentails-using-aws-command-line-interface
- Configure Knife (original prerequisite link): tutorials/configure-the-knife-command
- An AWS account with EC2 permissions, a key pair in your target region, and network access for SSH/bootstrap.
Provisioning workflow
flowchart TD
A[Install and configure Chef tooling] --> B[Export AWS credentials]
B --> C[Generate Chef repo and provision cookbook]
C --> D[Write default provisioning recipe]
D --> E[Generate Policyfile]
E --> F[Run chef install]
F --> G[Run chef provision]
G --> H[EC2 instance created and converged]
Set AWS environment variables
The original article expects AWS values to be exported in the shell before provisioning.
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"
export AWS_DEFAULT_REGION="us-east-1"
export AWS_SSH_KEY="your_ec2_key_pair_name"
# Legacy aliases used by some older examples
export AWS_ACCESS_KEY="$AWS_ACCESS_KEY_ID"
export AWS_SECRET_KEY="$AWS_SECRET_ACCESS_KEY"Code language: PHP (php)
| Variable | Purpose | In original workflow |
|---|---|---|
| AWS_ACCESS_KEY_ID | AWS API access key | Required |
| AWS_SECRET_ACCESS_KEY | AWS API secret key | Required |
| AWS_DEFAULT_REGION | Default region for AWS API calls | Required |
| AWS_SSH_KEY | EC2 key pair name used at launch | Required by sample recipe options |
| AWS_ACCESS_KEY / AWS_SECRET_KEY | Legacy alias variable names | Optional compatibility aliases |
Generate the repo and provisioning cookbook
Create a new repository and then add the provisioning cookbook used by this flow.
chef generate repo chefdk-provision-demo
cd chefdk-provision-demo
chef generate cookbook provision
Author the default provisioning recipe
Edit provision/recipes/default.rb and define your driver and machine options. The structure below mirrors the original article, with placeholders where appropriate.
context = ChefDK::ProvisioningData.context
with_driver 'aws::us-west-2'
options = {
ssh_username: 'admin',
use_private_ip_for_ssh: false,
bootstrap_options: {
key_name: ENV['AWS_SSH_KEY'],
image_id: 'ami-xxxxxxxx',
instance_type: 'm3.medium'
},
convergence_options: context.convergence_options
}
machine context.node_name do
machine_options options
action context.action
converge true
endCode language: PHP (php)
Key points: the AWS driver selects the region, bootstrap options define how the EC2 instance is created, and convergence options apply the intended Chef run list during provisioning.
Create and install a Policyfile
chef generate policyfile
$EDITOR Policyfile.rbCode language: PHP (php)
name "chefdk-provision-demo"
default_source :community
run_list "recipe[libuuid-user]"
cookbook "libuuid-user"Code language: JavaScript (javascript)
Install the Policyfile so dependencies are resolved and lock data is created before provisioning.
chef install
| Command | Purpose | Main output |
|---|---|---|
| chef generate repo chefdk-provision-demo | Initialize a Chef repository | Repo directory structure |
| chef generate cookbook provision | Create provisioning cookbook | provision/ cookbook files |
| chef generate policyfile | Create Policyfile template | Policyfile.rb |
| chef install | Resolve cookbook dependencies | Policyfile.lock.json and local cache |
| chef provision testing –sync -n debian-libuuid | Launch and converge target node | Provisioned EC2 instance with applied policy |
Provision the EC2 instance
chef provision testing --sync -n debian-libuuid
This command performs synchronization and converges the node name specified with -n. Validate region, key pair name, AMI, and SSH user before running.
Troubleshooting checkpoints
- Credentials exported in the same shell session running Chef commands.
- EC2 key pair exists in the same AWS region used by the driver.
- AMI ID is valid and available in that region/account.
- SSH username matches the selected AMI defaults.
- IAM permissions allow EC2 instance creation, tagging, and describe actions.
Reference and attribution
Original reference cited in the source post: http://jtimberman.housepub.org/blog/2015/05/15/quick-tip-chefdk-provision/
Best practices for maintaining this legacy workflow
- Keep credentials out of shell history; prefer short-lived credentials or profile-based auth where possible.
- Parameterize AMI ID, instance type, region, and SSH username instead of hardcoding.
- Commit
Policyfile.rband lockfile for reproducible convergence. - Run provisioning first in a non-production AWS account to validate recipe and bootstrap behavior.
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services — all in one place.
Explore Hospitals