Chef¶
On this page
Chef's model for configuration management: the resource/recipe/cookbook hierarchy, the pull-based agent run, and how to keep nodes in a declared state.
Basics¶
Chef (Progress Chef) is a configuration-management tool that describes a machine's
desired state as code (Ruby DSL) and converges nodes to that state. It is classically
pull-based and agent-based: each managed node runs chef-client, which fetches
policy from a Chef Infra Server (or runs locally) and applies it.
Core building blocks (smallest → largest)¶
| Concept | What it is |
|---|---|
| Resource | A declared piece of state: a package, service, file, template, user. |
| Recipe | An ordered collection of resources (a .rb file). |
| Cookbook | A package of recipes + templates, files, attributes, custom resources. |
| Attributes | Variables/data that parameterize recipes (defaults, overrides). |
| Run-list | The ordered set of recipes/roles applied to a node. |
| Role / Environment | Group nodes by function / lifecycle (dev, prod). |
| Data bags | Global JSON data (e.g. users, secrets via encrypted data bags). |
| Policyfiles | Modern way to pin cookbook versions for a node group (preferred over roles/environments). |
How a chef-client run works¶
- Build the node object and gather system facts via Ohai.
- Sync cookbooks from the Chef Infra Server (or use local mode /
chef-solo). - Compile recipes into a resource collection.
- Converge — execute each resource to reach desired state (idempotently).
- Report/handlers run.
Declarative + idempotent¶
You declare what should be true (package 'nginx' do action :install end), not the
steps. Chef makes changes only if the current state differs, so runs are safe to repeat.
Tooling¶
- Chef Workstation — author/test cookbooks; ships
chef,knife, Test Kitchen, InSpec, Cookstyle. - Chef Infra Client — the agent on nodes.
- Chef Infra Server — central store for cookbooks, node data, policy.
- Test Kitchen — spins up VMs/containers to test cookbooks.
- InSpec — compliance/security testing as code.
Cheatsheet¶
A minimal recipe¶
# cookbooks/web/recipes/default.rb
package 'nginx' do
action :install
end
template '/etc/nginx/nginx.conf' do
source 'nginx.conf.erb'
owner 'root'
group 'root'
mode '0644'
notifies :reload, 'service[nginx]', :delayed
end
service 'nginx' do
action [:enable, :start]
end
Common resources¶
file '/tmp/x' do content 'hello' end
directory '/opt/app' do recursive true end
user 'deploy' do shell '/bin/bash' end
execute 'reload-sysctl' do command 'sysctl -p' end
git '/srv/app' do repository 'https://...' revision 'main' end
cron 'cleanup' do minute '0' hour '2' command '/usr/local/bin/cleanup' end
CLI / workflow¶
chef generate cookbook web # scaffold a cookbook
chef generate recipe web extra
# knife (talks to Chef Infra Server)
knife cookbook upload web
knife node list ; knife node show NODE
knife bootstrap HOST -N name -r 'recipe[web]' # install client + run
knife ssl check
# local / standalone
chef-client --local-mode --runlist 'recipe[web]'
chef-client # normal run against server
# test & lint
kitchen test # Test Kitchen full cycle
cookstyle . # Ruby/style linting
inspec exec compliance-profile
Thumb Rules¶
Rules of thumb
- Declare state, don't script steps. Reach for a resource before
execute/bash. - Every run must be idempotent. If a second run changes things, the recipe is wrong.
- Use
notifies/subscribesfor restarts so services reload only when config changes. - Pin cookbook versions (Policyfiles) so prod doesn't drift when you publish updates.
- Secrets go in encrypted data bags or a vault, never plaintext in cookbooks.
- Test in Test Kitchen before uploading. Treat cookbooks like application code (lint, test, review).
- Attributes have precedence levels — keep overrides minimal and predictable.
Use Cases¶
- Fleet configuration — install/patch packages, manage users, deploy config across many servers.
- Golden-state enforcement — periodic chef-client runs correct drift automatically.
- Compliance as code — pair with InSpec for continuous security/compliance checks.
- Application deployment — provision the OS layer and app dependencies consistently.
- Hybrid/large enterprises — Chef is common where a pull-based, self-healing model is preferred.
Common Issues¶
Recipe not idempotent / changes every run
A execute/bash block runs unconditionally. Add a not_if/only_if guard or use a
proper declarative resource that knows its current state.
“Cookbook not found” or version conflicts
Dependency constraints in metadata.rb / Policyfile can't be satisfied. Run
berks/chef install to resolve, and pin versions. Re-upload with knife cookbook upload.
Service doesn't restart after config change
Missing notifies :restart, 'service[x]' on the template/file resource, or the service
resource name doesn't match. Confirm the notification target name.
SSL / client registration errors on bootstrap
Clock skew, wrong server URL, or missing validation key. knife ssl check, verify time
sync (chrony), and the node's client.rb.
Attribute precedence surprises
A value isn't what you expect because a higher-precedence level overrides it. Inspect
with node.debug_value('key') and reduce override sprawl.
Best Practices¶
- Adopt Policyfiles for deterministic, version-pinned node policy.
- Keep cookbooks small and single-purpose; compose via dependencies.
- Lint with Cookstyle, test with Test Kitchen, verify with InSpec in CI.
- Manage secrets with encrypted data bags or an external vault.
- Use roles/environments or policy groups to separate dev/stage/prod.
- Version-control everything and review changes like app code.
- Schedule regular chef-client runs so drift is corrected continuously.
- Document attributes and their defaults clearly.
Official Sources¶
- Chef documentation — https://docs.chef.io/
- Chef Infra Language & resources — https://docs.chef.io/resources/
- Chef Workstation — https://docs.chef.io/workstation/
- Policyfiles — https://docs.chef.io/policyfile/
- Test Kitchen — https://kitchen.ci/
- InSpec (compliance) — https://docs.chef.io/inspec/
- Chef Supermarket (community cookbooks) — https://supermarket.chef.io/