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.

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.
First, make sure the installation from episode 0 is still intact. Verify all the main binaries:
chef -v
knife -v
berks -v
kitchen versionWarning
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:
| Binary | Role | Runs on |
|---|---|---|
chef | Generator & development utilities | Workstation |
chef-client | Agent that converges nodes | Node |
knife | CLI for interacting with the Infra Server | Workstation |
berks | Cookbook dependency manager | Workstation |
kitchen | Test Kitchen for testing | Workstation |
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 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-clientchef-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.
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.
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).
cd ~/lab-chef/chef-repo
knife zero bootstrap localhost --ssh-user devops --sudo \
--node-name node-01
# Verify the node is registered
knife node listnode-01Important
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:
knife ssh 'name:node-01' 'sudo chef-client' --ssh-user devopsNow the most fun part: creating a cookbook. Chef provides a generator that creates the complete structure automatically.
cd ~/lab-chef
chef generate cookbook nginxThe 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.Let's write a simple recipe that installs nginx and makes sure its service is running.
#
# Cookbook:: nginx
# Recipe:: default
#
package 'nginx' do
action :install
end
service 'nginx' do
action [:enable, :start]
endNote
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.
Run that cookbook on a test node using zero mode:
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 devopsStarting 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 updatedThe - 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:
knife ssh 'name:node-01' 'curl -sI http://localhost | head -n 1' --ssh-user devopsHTTP/1.1 200 OKIn 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:
chef generate cookbook produces the standard structure: recipes/, attributes/, templates/, files/, and metadata.rb.- 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.