Chef Fundamentals
Chef is an infrastructure automation framework that uses code to define and manage your infrastructure. It enables teams to automate the provisioning, configuration, and management of systems at scale.
What is Chef?
Chef automates infrastructure management by allowing you to express configuration as code. It follows a declarative model: you define desired state, and Chef ensures systems converge to that state.
Core philosophy:
- Infrastructure as Code — Version control your infrastructure
- Idempotent — Safe to run multiple times
- Declarative — Define "what" not "how"
- Convergence — Systems reach desired state through repeated runs
Chef Components
The Chef Ecosystem
┌─────────────────────────────────────────────────┐
│ Chef Workstation │
│ - Chef CLI, Knife, Test Kitchen, Cookstyle │
└──────────────────────┬──────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌──────────────┐
│Cookbooks│ │InSpec │ │Chef Automate │
│Recipes │ │Tests │ │(dashboards) │
└────┬────┘ └─────────┘ └──────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Chef Infra Server │
│ - Cookbooks, Policies, Node data │
└──────────────────────┬──────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Node A │ │ Node B │ │ Node C │
│Chef- │ │Chef- │ │Chef- │
│client │ │client │ │client │
└─────────┘ └─────────┘ └─────────┘
Chef Concepts
Cookbooks
A cookbook is a collection of recipes, attributes, templates, and files that define infrastructure. It's the basic unit of reusable code in Chef.
my_cookbook/
├── recipes/ # Recipe definitions
│ ├── default.rb
│ ├── install.rb
│ └── configure.rb
├── attributes/ # Default values
│ ├── default.rb
│ └── packages.rb
├── templates/ # File templates
│ └── app.conf.erb
├── files/ # Static files
│ └── config.yaml
├── metadata.rb # Cookbook metadata
├── README.md
└── CHANGELOG.md
Recipes
Recipes are Ruby code that defines resources and actions.
# recipes/default.rb
# Update package manager
execute 'update-packages' do
command 'apt-get update'
action :run
end
# Install package
package 'nginx' do
action :install
end
# Create directory
directory '/var/www/html' do
mode '0755'
recursive true
end
# Create file from template
template '/etc/nginx/sites-available/default' do
source 'nginx.conf.erb'
variables(
server_name: node['nginx']['server_name']
)
notifies :restart, 'service[nginx]'
end
# Manage service
service 'nginx' do
action [:enable, :start]
end
Resources
Resources are the building blocks of recipes. Each resource represents a system component.
# Core resources
package 'nginx' # Install package
service 'nginx' # Manage service
file '/etc/config.conf' # Manage file
directory '/var/www' # Manage directory
user 'deploy' # Manage user
group 'webadmins' # Manage group
template 'app.conf.erb' # Template file
cron 'daily-backup' # Cron job
execute 'custom-command' # Run command
git '/app/repo' # Clone git repo
template_file '/etc/app.conf' # Template-based file
Attributes
Attributes are variables that define node configuration. They have precedence levels.
# attributes/default.rb
# Simple attribute
default['nginx']['version'] = '1.20.0'
# Nested attribute
default['app']['database'] = {
host: 'localhost',
port: 5432,
name: 'app_db'
}
# Array attribute
default['app']['enabled_modules'] = ['auth', 'logging', 'caching']
# Using attributes in recipes
package "nginx-#{node['nginx']['version']}" do
action :install
end
template '/etc/app.conf' do
variables(
db_host: node['app']['database']['host'],
db_port: node['app']['database']['port']
)
end
Precedence Levels (Low to High)
default— Default values (lowest priority)force_default— Override defaultsnormal— User values (persisted)override— Override normal valuesforce_override— Override everythingautomatic— System facts (highest priority)
Roles
Roles group recipes and attributes for specific purposes.
# roles/webserver.rb
name 'webserver'
description 'Web server role'
run_list(
'recipe[nginx::install]',
'recipe[nginx::configure]',
'recipe[ssl::install]'
)
override_attributes(
'nginx' => {
'worker_processes' => 4,
'keepalive_timeout' => 65
},
'ssl' => {
'cert_path' => '/etc/ssl/certs'
}
)
Environments
Environments separate infrastructure stages (dev, staging, prod).
# environments/production.rb
name 'production'
description 'Production environment'
override_attributes(
'app' => {
'debug' => false,
'log_level' => 'warn'
},
'nginx' => {
'worker_processes' => 8
},
'database' => {
'pool_size' => 50,
'timeout' => 30
}
)
Chef Infra Server
Chef Infra Server is the central hub for Chef infrastructure management.
Server Components
- Cookbook Management — Store and version cookbooks
- Node Data — Track node attributes and state
- Policy — Define which cookbooks run on which nodes
- Authentication — Secure node-to-server communication
Chef Server Workflow
1. Develop cookbooks locally (Chef Workstation)
2. Upload cookbooks to Chef Server
3. Define node run-lists or policies
4. Chef Client pulls configuration from server
5. Client converges system to desired state
6. Server collects node data for reporting
Chef Workstation
Chef Workstation provides tools for local development:
- Chef Infra Client — Converges system configuration
- Knife — Command-line tool for server interaction
- Test Kitchen — Testing framework for cookbooks
- Cookstyle — Ruby code analyzer (replaced Foodcritic)
- InSpec — Infrastructure testing framework
Knife Commands
# Upload cookbooks to server
knife cookbook upload my_cookbook
# List cookbooks on server
knife cookbook list
# Manage nodes
knife node list
knife node show node-name
# Manage roles
knife role create webserver
knife role list
# Bootstrap new node
knife bootstrap 192.168.1.100 -x ubuntu -i ~/.ssh/id_rsa
Chef Policies
Modern approach to managing cookbook versions on nodes.
# Policyfile.rb
name 'web_server'
run_list 'recipe[nginx::install]', 'recipe[ssl]'
cookbook 'nginx', '~> 8.0'
cookbook 'ssl', '~> 2.0'
default_source :supermarket
named_run_list :with_monitoring, 'recipe[monitoring]'
Chef InSpec
Infrastructure testing framework integrated with Chef.
# test/integration/default/nginx_spec.rb
describe package('nginx') do
it { should be_installed }
end
describe service('nginx') do
it { should be_installed }
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
its('protocols') { should include 'tcp' }
end
describe http('http://localhost') do
its('status') { should eq 200 }
its('body') { should match /Welcome/ }
end
Test Kitchen
Testing framework for cookbook development.
# kitchen.yml
driver:
name: vagrant
provisioner:
name: chef_zero
platforms:
- name: ubuntu-20.04
- name: centos-8
suites:
- name: default
run_list:
- recipe[my_cookbook::default]
verifier:
inspec_tests:
- test/integration/default
Test Kitchen Commands
# Create test instances
kitchen create
# Converge (run chef)
kitchen converge
# Run tests
kitchen verify
# Destroy instances
kitchen destroy
# Single command
kitchen test
Chef Automate
Dashboard and analytics platform for Chef infrastructure.
- Real-time visibility into infrastructure
- Node and compliance dashboards
- Role-based access control
- Integration with third-party systems
- Data APIs for custom reporting
Idempotence
Chef resources are idempotent — they only make changes when needed.
# This resource is safe to run multiple times
package 'nginx' do
action :install
end
# First run: installs nginx
# Second run: detects nginx installed, does nothing
# Third run: same as second run
# Idempotent with guards
execute 'install-ruby' do
command './install_ruby.sh'
not_if { ::File.exist?('/opt/ruby/bin/ruby') }
end
# Only runs if Ruby isn't already installed
Exercises
Exercise 1: Basic Recipe
- Create a cookbook with a recipe
- Define resources (package, file, service)
- Use attributes for configuration
- Test with
kitchen test
Exercise 2: Role and Attributes
- Create a role for web server
- Define environment-specific attributes
- Apply role to a test node
- Verify convergence
Exercise 3: Templates
- Create a template for configuration file
- Use attributes in template
- Add notification to restart service
- Test template rendering
Exercise 4: Integration Tests
- Write InSpec tests for resources
- Create Test Kitchen configuration
- Converge and verify
- Test multiple platforms
Exercise 5: Multi-Cookbook Application
- Create multiple dependent cookbooks
- Define run-list with multiple recipes
- Use cookbook dependencies
- Package and upload to server
Common Patterns
NTP Server Configuration
# recipes/ntp.rb
package 'ntp' do
action :install
end
template '/etc/ntp.conf' do
source 'ntp.conf.erb'
notifies :restart, 'service[ntp]'
end
service 'ntp' do
action [:enable, :start]
end
User and Sudo
# recipes/users.rb
user 'deploy' do
shell '/bin/bash'
home '/home/deploy'
manage_home true
end
group 'sudo' do
members ['deploy']
append true
end
Application Deployment
# recipes/deploy.rb
git '/opt/myapp' do
repository 'https://github.com/example/myapp.git'
revision 'main'
action :sync
notifies :run, 'execute[install-dependencies]'
end
execute 'install-dependencies' do
cwd '/opt/myapp'
command 'bundle install'
action :nothing
end
Summary
Chef provides:
- Infrastructure as Code — Version-controlled configuration
- Idempotent operations — Safe repeated runs
- Scalable management — Thousands of nodes
- Flexibility — Ruby-based DSL for complex logic
- Integration — Works with existing tools and cloud providers
Master Chef to automate and scale infrastructure management across your organization.