Learn Chef - Setup & Installation
Series/Learn Chef/Episode 3
Episode 3 of 23

Learn Chef - Setup & Installation

In this episode we will practice hands-on: installing Chef Workstation and Chef Client, running chef-client in client, solo, and zero modes, bootstrapping a node, and creating the first cookbook.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 2 you understood the Chef architecture conceptually: the five-phase chef-client flow, the role of Workstation, Chef Infra Server, and Nodes, as well as the core components. Now it's time to get our hands dirty and touch the tools directly. Remember the saying in the automation world: "you don't really understand until you practice it".

Episode 3 is a hands-on episode. We will install Chef Workstation and Chef Client, run chef-client in three development modes (client, solo, and zero), bootstrap a node from the workstation, and create the first cookbook structure with chef generate cookbook nginx. By the end of the episode, you will have a real cookbook that successfully converges on a test node.

Chef Workstation & Chef Client

First, make sure the installation from episode 0 is still intact. Verify all the main binaries:

Verify Chef Workstation installation
chef -v
knife -v
berks -v
kitchen version

Warning

If any command is not found, don't continue yet. Repeat the Chef Workstation installation (episode 0) and make sure the eval "$(chef shell-init bash)" command is already in your ~/.bashrc file, then run source ~/.bashrc.

Chef Client is the agent that runs on nodes. By default Chef Workstation already bundles Chef Infra Client, so for local practice you don't need to install it separately. The difference in roles:

BinaryRoleRuns on
chefGenerator & development utilitiesWorkstation
chef-clientAgent that converges nodesNode
knifeCLI for interacting with the Infra ServerWorkstation
berksCookbook dependency managerWorkstation
kitchenTest Kitchen for testingWorkstation

Development Modes: client, solo, and zero

For home practice, we don't need to stand up a full Chef Infra Server right away. Chef provides three modes, each with its own purpose.

client mode (chef-client) and solo mode (chef-solo)

Client mode is the normal production mode: chef-client communicates with the Chef Infra Server, pulls the run_list and cookbooks, then converges — it needs a running server and a client.rb configuration. Solo mode, on the other hand, is completely self-contained with no server at all: chef-solo reads cookbooks directly from a local directory and applies them, suitable for isolated nodes even without a node registry or centralized data bags.

sudo chef-client

zero mode (chef-zero / chef-client -z)

chef-zero is a fake in-memory server that runs on the workstation. It functionally mimics the Chef Infra Server — supporting knife, data bags, environments, node registry — without persisting anything permanently. Zero mode has become the modern development standard because its behavior is closest to production without the hassle of setting up a server.

Run chef-client in zero mode
cd ~/lab-chef/chef-repo
knife zero bootstrap localhost --ssh-user devops
 
# Or run chef-client directly with -z
chef-client -z -r 'recipe[nginx]'

Tip

For practice in this series, zero mode is the best choice: knife commands like knife node list still work, but there is no server to maintain. In episode 9 we'll switch to a real Chef Infra Server.

Bootstrapping a Node from the Workstation

Bootstrap is the process of installing Chef Infra Client on a new node and registering it with the server, all done from the workstation over SSH. With zero mode, we can easily bootstrap a local node (or an accessible container/VM).

Bootstrap a node from the workstation (zero mode)
cd ~/lab-chef/chef-repo
knife zero bootstrap localhost --ssh-user devops --sudo \
  --node-name node-01
 
# Verify the node is registered
knife node list
Sample knife node list output
node-01

Important

Bootstrap requires SSH access to the node and an account with sudo privileges. Make sure your SSH key is already installed on the node (ssh-copy-id) and that the user has passwordless sudo access so the bootstrap process runs smoothly.

After bootstrapping, the node runs chef-client periodically (default every 30 minutes via cron/service scheduler). We can test one configuration command directly from the workstation:

Run chef-client on node-01 from the workstation
knife ssh 'name:node-01' 'sudo chef-client' --ssh-user devops

Creating the First Cookbook

Now the most fun part: creating a cookbook. Chef provides a generator that creates the complete structure automatically.

Generate a new cookbook structure
cd ~/lab-chef
chef generate cookbook nginx

The generated structure above is the standard Chef cookbook layout. A few directories you will use often:

  • recipes/ — where recipe files live (default.rb is the entry point).
  • attributes/ — default cookbook attribute values.
  • templates/ — templated configuration files (ERB).
  • files/ — static files copied as-is.
  • libraries/ — custom Ruby modules.
  • metadata.rb — cookbook description: name, version, dependencies.

Writing the First Recipe

Let's write a simple recipe that installs nginx and makes sure its service is running.

recipes/default.rb
#
# Cookbook:: nginx
# Recipe:: default
#
 
package 'nginx' do
  action :install
end
 
service 'nginx' do
  action [:enable, :start]
end

Note

Notice the Chef resource pattern: a resource name (string), then a do ... end block containing properties (action, and later many other properties). The package resource handles distro differences automatically — on Debian it uses apt, on RHEL it uses yum/dnf.

Converging the First Cookbook

Run that cookbook on a test node using zero mode:

Converge the nginx cookbook onto node-01
cd ~/lab-chef/chef-repo
knife cookbook upload nginx
knife node run_list set node-01 'recipe[nginx]'
knife ssh 'name:node-01' 'sudo chef-client' --ssh-user devops
Snippet of a successful chef-client output
Starting Chef Infra Client, version 19.x
...
Recipe: nginx::default
  * package[nginx] action install
    - install version 1.24.0 of package nginx
  * service[nginx] action enable
    - enable service service[nginx]
  * service[nginx] action start
    - start service service[nginx]
Chef Infra Client finished, 3/3 resources updated

The - install ... and - start ... markers mean resources changed. Run it again and observe the difference — on the second run there are no - markers because the state already matches. That's idempotency working for real.

To close the practice session, verify that nginx really responds to HTTP requests on node-01:

Verify nginx is running on node-01
knife ssh 'name:node-01' 'curl -sI http://localhost | head -n 1' --ssh-user devops
Expected output
HTTP/1.1 200 OK

Conclusion

In episode 3 we practiced hands-on: installing and verifying Chef Workstation, understanding the three development modes (client, solo, zero), bootstrapping a node with knife zero bootstrap, creating the nginx cookbook with chef generate cookbook, and converging it onto a test node with idempotent results.

Key takeaways:

  • The three development modes are client (needs a server), solo (no server), and zero (fake in-memory server) — use zero for practice.
  • Bootstrap a node is done from the workstation over SSH to install and register chef-client.
  • chef generate cookbook produces the standard structure: recipes/, attributes/, templates/, files/, and metadata.rb.
  • Idempotent resources are marked by no changes on the second run — the - marker only appears when the state differs.
  • knife node list, knife node run_list set, knife ssh are the three core commands for managing nodes from the workstation.

Now you have a real cookbook that successfully converges. In the next episode, episode 4, we will dissect resources & recipes in depth — the eight basic resources (package, service, file, template, execute, directory, user, group), their properties and actions, and how to compose recipes declaratively and correctly.