Chef Server

Download and Install

On Centos 8:




sudo dnf localinstall -y $INSTALL_DIR/chef-server-core-14.1.0-1.el7.x86_64.rpm


Start by setting the following variables to correspond with the commands below:

ORG_FULL_NAME="Organization Inc."

Install Chef server and automatically accept the license:

sudo chef-server-ctl reconfigure --chef-license=accept

Show status of server

sudo chef-server-ctl status

Create new user

The key at ${KEY_PATH} will be used by a workstation at a later time. Specifically, it is the private key for the user to auth to the chef server.

sudo chef-server-ctl user-create ${USERNAME} ${FIRST_NAME} ${LAST_NAME} ${EMAIL} -f ${KEY_PATH} --prompt-for-password

password as CLI arg:

Include password in command line (don’t do this in anything but a dev environment, and even then this is probably not a good idea):

sudo chef-server-ctl user-create ${USERNAME} ${FIRST_NAME} ${LAST_NAME} ${EMAIL} "password_you_create_for_the_user" -f ${KEY_PATH}

List users

sudo chef-server-ctl user-list

Delete user

sudo chef-server-ctl user-delete ${USERNAME}

Also remove from admin-group and answer yes to prompt:

sudo chef-server-ctl user-delete ${USERNAME} --remove-from-admin-groups -y

Create new org

sudo chef-server-ctl org-create ${ORG_NAME} ${ORG_FULL_NAME}

Associate user and path to validator key:

sudo chef-server-ctl org-create ${ORG_NAME} ${ORG_FULL_NAME} --association_user ${USERNAME} --filename ${VALIDATION_KEY_PATH}

List orgs

sudo chef-server-ctl org-show
sudo chef-server-ctl org-list

Delete orgs

sudo chef-server-ctl org-delete ${ORG_NAME}
# Answer yes to prompt automatically:
sudo chef-server-ctl org-delete ${ORG_NAME} -y


Chef Workstation

Download and setup

On Centos 8:




sudo dnf localinstall -y $INSTALL_DIR/chef-workstation-21.2.303-1.el7.x86_64.rpm

Confirm everything is installed

chef --version
knife --version

Configure workstation repo

chef generate repo $REPO_NAME --chef-license accept


# Set up git
git config --global gitusername
git config --global
echo ".chef" > .gitignore

# Configure knife
mkdir .chef
cd .chef
touch knife.rb

Configure Knife

This is the utility that you’ll use to communicate with the Chef server from your Workstation.

Start by getting the private key from the chef server. You may use scp for something like this:

CHEF_SERVER=chef-server.local # replace me with your chef-server address
KEY_LOC=/home/chefadmin.pem # replace me with the location of your key on the chef server

Add info to knife file

The file should look something like this:

current_dir = File.dirname(__FILE__)
log_level                :info
log_location             STDOUT
# The username to auth to chef server with -or- name of the machine knife is run in - we are going with the username here
node_name                "chefadmin"
client_key               "#{current_dir}/chefadmin.pem"
validation_client_name   "myorg-validator"
validation_key           "/etc/chef/myorg-validator.pem"
chef_server_url          "https://chef-server/organizations/myorg"
cookbook_path ["#{current_dir}/../cookbooks"]

Be sure to change the values for node_name, client_key, validation_client_name, validation_key, and chef_server_url to match your settings from the chef server. There are commands above and here to help you to get this information, though you’ll need to run them on the chef server.

Get SSL cert from the server

knife ssl fetch
knife ssl check

Confirm knife is setup properly

If the validator name is output from running this command:

knife client list

then you’re in good shape.

At this point, you can run cd .. and create a cookbook.

Create basic cookbook

We will create a cookbook that will create a text file for the room user in /tmp/hello.txt on the chef node.

To start, run these commands:

export COOKBOOK_LOC=cookbooks
export COOKBOOK_NAME=hello
chef generate cookbook $COOKBOOK_LOC/$COOKBOOK_NAME

Next, run this script populate the cookbook content:

cat <<EOT >> $COOKBOOK_LOC/$COOKBOOK_NAME/recipes/default.rb
cookbook_file '/tmp/hello.txt' do
  source 'hello.txt'
  owner 'root'
  group 'root'
  action :create

Once that’s done, upload the cookbook to the chef server:

knife cookbook upload hello

and confirm it’s there:

knife cookbook list

Now you’ll want to run this on a chef node. First we will need to bootstrap one.

Bootstrap a chef node

First, you need to have an ssh key pair that allows you to talk to the node(s). You can generate a pair with this command:

ssh-keygen -t rsa -m PEM -C "Chef SSH Key" -f "chef_ssh_key" -N ''

and then scp the public key into the authorized_keys file for the $USER you have set up on the chef node.

You’ll also want to make sure the permissions are correct on this system - here’s a resource to help.

Note: The $USER you use on the chef node must have sudo privileges to work properly with chef!

Alternatively, you can use password authentication.

An example can be found below (although you will need your ssh config to be properly configured to go this route). An example of an environment that uses that mechanism can be found here.

With the keys in place, make sure your target node is in your /etc/hosts file on the workstation. If it’s not, add it:

echo -e "$NODE_IP $NODE_FQDN $NODE_HOSTNAME" | sudo tee -a /etc/hosts

Next, run this command to bootstrap the node with the hello cookbook we created:

knife bootstrap $NODE_HOSTNAME -U $USER --ssh-identity-file chef_ssh_key --sudo --node-name $NODE_HOSTNAME --run-list 'recipe[hello]'

If you’re running this as part of some automated job, make sure to add --ssh-verify-host-key never like so:

knife bootstrap $NODE_HOSTNAME -U $USER --ssh-identity-file chef_ssh_key --ssh-verify-host-key never --sudo --node-name $NODE_HOSTNAME --run-list 'recipe[hello]'



Chef Vault is a utility to encrypt data bag items using asymmetric keys.

Create a secret

knife vault create passwords root '{"username": "root", "password": "mypassword"}'

List secrets vaults

knife vault list

Show secrets in a vault

secret_vault is the vault in this case:

knife vault show secret_vault

Get value of a vault secret

knife vault show <vault name> <secret name>

For example:

knife vault show secret_vault mysql_pw

Create a secret in a vault

knife vault create secret_vault postgresql_pw '{"user":"postgresql", "password": "TheM0stS3cr3T!!!"}'

Get node information

knife search node 'name:<node name>' -a chef_client

For example:

knife search node 'name:chef-agent-2' -a chef_client

Show which nodes are running a recipe

knife search node "recipes:<recipe_name>"


Get all nodes

knife node list

Get all linux nodes

knife search node "os:linux"

Add cookbook to a run_list for a chef node

knife node run_list add <node name> <cookbook name>

For example:

knife node run_list add chef-node evil

Remove cookbook from run_list for a chef node

knife node run_list remove <node name> recipe[<cookbook name>]

For example:

knife node run_list remove chef-agent-1 recipe[my_cmd]

Remove cookbook from chef server

knife cookbook delete $COOKBOOK_NAME

Upload/Update Cookbook

knife cookbook upload $COOKBOOK_NAME

List cookbooks

knife cookbook list

Show run_list for a chef node

knife node show <node name>

Show run_lists for all chef nodes

knife exec -E 'nodes.all {|n| puts "#{} has #{n.run_list}"}'


Download a cookbook from the supermarket

knife supermarket download <cookbook name>

For example:

knife supermarket download learn_chef_apache2

Upload cookbooks en masse

knife upload cookbooks

Bootstrap a chef node w/ a password

knife bootstrap <node name> -u root -P toor --sudo -N <node name> --run-list 'recipe[hello], recipe[chef-client::config]'"

For example:

knife bootstrap chef-agent-1 -u root -P toor --sudo -N chef-agent-1 --run-list 'recipe[hello], recipe[chef-client::config]'"