Community Blog Getting started with Chef

Getting started with Chef

In this tutorial, you will learn about Chef and how you can use it to set up, build, and deploy a simple React.js site on Alibaba Cloud.

By Kehinde Sanni, Alibaba Cloud Community Blog author.

Chef is an open-source configuration management tool written in Ruby and Erlang. It uses a pure-Ruby, domain-specific language (DSL) for writing system configuration. Chef transforms infrastructure into code so to help automate server deployment and management. So, whether you're operating in the cloud, on-premises, or in a hybrid environment, Chef can help you to automate your infrastructure, helping to configure, deploy, and manage it across your network, no matter its size.

In this tutorial, you will learn the basics of Chef, and build a simple React.js site using Chef on an Alibaba Cloud ECS instance with Ubuntu installed. By the end of this tutorial, you'll have learned the basics of Chef, how to set up a Chef server, node and workstation, and be able to deploy a minimal application.


To follow this tutorial, you will need:

  • Two Alibaba Cloud Elastic Compute Service (ECS) instances installed with Ubuntu 16.04 that have at least 2 GBs of RAM. One of these instances will be used for the Chef node, and the other for the Chef server. Also, for these instances, ensure that port 22, 80, and 443 are open.
  • A fully-qualified registered domain (or FDQN) to use for both the Chef node and server. You can purchase an Alibaba Cloud domain or get one free with Freenom.

Getting to Know Chef

Chef is made up of several different components. It's important to understand these components, so here let's quickly look at the three major components of Chef.

  • Chef server: This component acts as a hub for configuration data and serves as the central location where configuration recipes, cookbooks, the policies that are applied to nodes, and metadata that describes each registered node that is being managed by Chef are all stored. This component also is the central machine that every other machine (or node) in an organization will use for deployment configuration purposes.
  • Nodes: The important component of nodes can be understood as machines, either physical or virtual ones, which you can manage using Chef. The Chef-client is installed on each node and is used to configure each node to your desired state. Nodes use the chef-client to interact with the chef server and obtain configuration information such as recipes, templates, and file distribution.
  • Workstation: Chef workstations are where Chef configuration information is created or edited. Configuration files are pushed to the Chef server, where they are available to deploy to any nodes. Interaction with the chef server from the workstation is done using the knife and chef command line tools.

Setting up Your Environment

Now it's time to do something practical. In this leg of the tutorial, you will set up your environment and install the necessary tools required to build your React.js application with chef.

Setting up the Workstation

Recall that your workstation is basically where you author your chef configuration details. Your workstation can be any OS you choose be it. So, Linux, MacOS, and Windows all work here.

1.  Install the ChefDK package. The Chef DK (Development Kit) contains all the tools you will need to develop and test your infrastructure. You are using the current stable version, which is 4.0.60 as at the time of my writing this tutorial. Click on this link to download the Chef DK based on your OS.

2.  Verify that you have installed Chef DK and ensure that you can access the Chef DK from your command line. To do this, you can run chef --version to verify your installation.

   chef@workstation:~$ chef --version
   Chef Development Kit Version: 4.0.60
   chef-client version: 15.0.300
   delivery version: master
   berks version: 7.0.8
   kitchen version: 2.2.5
   inspec version: 4.3.2

3.  For Mac and Linux users, you need to ensure that the version of Ruby that is included with your Chef development kit is configured as the default version of Ruby. To do this, follow these steps:

  • Open your terminal and run which ruby. You should get something similar to the result as shown below
       chef@workstation:~$ which ruby
  • Using the chef shell-init sub-command, you will need to set the Ruby included in ChefDK as the system Ruby. ChefDK allows for applications used by chefDK to be isolated from other Ruby development tools, which may also be present on the workstation.

     chef@workstation:~$ echo 'eval "$(chef shell-init bash)"' >> ~/.bash_profile && source ~/.bash_profile

If you're using a shell different from bash such as zsh, fish, or Windows PowerShell (posh), run the command below, replacing SHELL_NAME with your shell and .SHELL_PROFILE with your shell profile.

     chef@workstation:~$ echo 'eval "$(chef shell-init SHELL_NAME)"' >> ~/.SHELL_PROFILE && source ~/.SHELL_PROFILE
  • You'll run the which ruby command again to confirm you are using the Chef development kit version of ruby and you should get the output shown below.
      chef@workstation:~$ which ruby

4.  Next, you will need to create a working directory, which will specifically be react-app-repo for your workstation. You are going to use the chef generate repo REPO_NAME command for this. This would create the necessary files and folder structure required by Chef.

    chef@workstation:~$ chef generate repo react-app-repo && cd react-app-repo

5.  Now that you are done setting up the workstation, you will go ahead to set up and configure the Chef server.

Setting up the Chef Server

To set up your Chef server, you can follow these steps:

1.  Spin up an Alibaba Cloud ECS instance installed with Ubuntu 16.04 as the Chef server and ensure port 80, 22 and 443 are open. If you're running Chef server in the cloud, ensure these ports are open through your security group.

2.  Your Chef server must have a resolvable domain and hostname. You will need to ensure that your server's hostname matches it public hostname. You can do so by running the command below:

      chef@chef_server:~$ echo YOUR_DOMAIN_NAME | xargs sudo hostname

3.  For learning purposes, I've created a bash script below for this tutorial. This should be helpful for you when it comes to downloading and installing the Chef-server package:

  • Copy the script below to the path /tmp/installChefServer.sh on your server
      chef@chef_server:~$ sudo vi /tmp/installChefServer.sh
      #!/usr/bin/env bash


      updateLinuxPackages() {
        printf "${BOLD}${GREEN}=================================== Updating all packages ============================================ ${NC}\n"
        apt-get update


      createDirectories() {
        if [ ! -d /creds ]; then
          mkdir /creds
        if [ ! -d /downloads ]; then
          mkdir /downloads

      downloadAndInstallChefServer() {
        if [ ! -f /downloads/chef-server-core_12.19.26-1_amd64.deb ]; then
          printf "${BOLD}${GREEN}=================================== Downloading the Chef server package... ================== ${NC}\n"
          wget -nv -P /downloads https://packages.chef.io/files/stable/chef-server/12.19.26/ubuntu/16.04/chef-server-core_12.19.26-1_amd64.deb

        if [ ! $(which chef-server-ctl) ]; then
          printf "${BOLD}${GREEN}=================================== Installing Chef server =================================== ${NC}\n"
          dpkg -i /downloads/chef-server-core_12.19.26-1_amd64.deb
          chef-server-ctl reconfigure

          printf "${BOLD}${GREEN}=================================== Waiting for services ====================================== ${NC}\n"
          until (curl -D - http://localhost:8000/_status) | grep "200 OK"; do sleep 15s; done
          while (curl http://localhost:8000/_status) | grep "fail"; do sleep 15s; done

          printf "${BOLD}${GREEN}============================= Creating user ========================== ${NC}\n"
          # creating user format: chef-server-ctl user-create USER_NAME FIRST_NAME LAST_NAME EMAIL 'PASSWORD' --filename FILE_NAME
          chef-server-ctl user-create admin admin admin admin@example.com 'notsecure' --filename /creds/chefadmin.pem
          printf "${BOLD}${GREEN}============================= Creating oganization with user ========================== ${NC}\n"
          # creating org format: chef-server-ctl org-create SHORT_ORG_NAME 'FULL_ORG_NAME' --association_user USER_NAME --filename FILE_NAME
          chef-server-ctl org-create chef "Chef-learn, Inc." --association_user admin --filename organization-validator.pem
          printf "${BOLD}${GREEN}============================= Adding Web UI for chef  ========================== ${NC}\n"
          chef-server-ctl install chef-manage
          chef-server-ctl reconfigure
          chef-manage-ctl reconfigure --accept-license

        printf "${BOLD}${GREEN}==================================== Your Chef server is ready! ================================== ${NC}\n"

      main() {

  • This script also creates a user with the following information:

    • Username: admin
    • Firstname: admin
    • Lastname: admin
    • Email: admin@example.com
    • Password: notsecure

  • Make the script executable by running the command below:
      chef@chef_server:~$ sudo chmod u+x /tmp/installChefServer.sh
  • Finally, run the script. This might take a while.
      chef@chef_server:~$ sudo /tmp/installChefServer.sh

4.  You can access the Chef web interface on your browser with your hostname.


Configuring the Workstation to Communicate with Chef Server

To establish communication between your workstation and the Chef server, you are going utilize the Knife utility tools already included with the ChefDK.

Basically, Knife requires two files to authenticate which the Chef server

  • A knife configuration file knife.rb, which contains information such as the Chef server's URL, the location of your RSA private key (SSH key), and the default location of your cookbooks.
  • An RSA private key, which is used to authenticate every request send to the Chef server. The Chef server holds the public part, while the workstation holds the private part.

Follow the steps below to establish communication between the workstation and Chef server

1.  Create the knife configuration by running the knife configure command.

Replace YOUR-HOST-NAME with your chef-server domain name and SHORT-ORG-NAME with chef. Also, keep a note of the path specified in the output to place the client key. you will use that next.

    chef@workstation:~$ knife configure
    WARNING: No knife configuration file found. See https://docs.chef.io/config_rb_knife.html for details.
    Please enter the chef server URL: [https://devops1c.mylabserver.com/organizations/chef]: https://YOUR-HOST-NAME/organizations/SHORT-ORG-NAME
    Please enter an existing username or clientname for the API: [user] admin
    You must place your client key in:
    Before running commands with Knife

    Configuration file written to /home/user/.chef/credentials

2.  You will need to create a knife.rb file in your react-app-repo directory to ensure that knife knows the location of your cookbooks.

    chef@workstation:~$ mkdir .chef && echo 'cookbook_path ["#{File.dirname(__FILE__)}/../cookbooks"]' >> .chef/knife.rb

You also need to copy over the SSH key file you created when you created your user with the installChefServer.sh script using scp command from your chef-server to your workstation.

Note ~/.chef/admin.pem is the path specified to place the client key, change this if it's different from the path specified on the output of your knife configure command.

Then, replace with following items:

IP-ADDRESS-OR-HOSTNAME replace with the public IP-address/hostname of your chef-server

USER replace with the name of the user on your chef-server

PATH_TO_YOUR_SSH_KEY replace with the path to your chef-server ssh-key

    chef@workstation:~$ scp -i PATH_TO_YOUR_SSH_KEY USER@YOUR-IP-ADDRESS-OR-HOSTNAME:/creds/chefadmin.pem ~/.chef/admin.pem

Alternatively, you can run the command below if you are using password as means of authentication to gain access to your server.

    chef@workstation:~$ scp USER@YOUR-IP-ADDRESS-OR-HOSTNAME:/creds/chefadmin.pem ~/.chef/admin.pem

3.  Next, you will need to fetch and validate the SSL certificate from your Chef server using the command below

    chef@workstation:~$ knife ssl fetch
    WARNING: Certificates from www.mydomainname.com will be fetched and placed in your trusted_cert
    directory (/home/user/.chef/trusted_certs).

    Knife has no means to verify these are the correct certificates. You should
    verify the authenticity of these certificates after downloading.

    Adding certificate for www_mydomainname_com in /home/user/.chef/trusted_certs/www_mydomainname_com.crt

Run the knife ssl check command to verify the SSL configuration.

     chef@workstation:~$ knife ssl check
     Connecting to host ec2-34-207-124-26.compute-1.amazonaws.com:443
     Successfully verified certificates from ec2-34-207-124-26.compute-1.amazonaws.com

Now your workstation is set up and you can connect to the Chef server using knife. In the next part, you'll set up the node

Setting up and Bootstrapping the Node

Before you can start working with Chef to manage configuration, you will need to have a node to work with. To do this, you'll create another ECS instance with Ubuntu 16.04 installed, and utilize the Knife and bootstrap subcommand from your workstation. You just need to create the Node server and most of the work will be done from the workstation

1.  Create another Alibaba Cloud instance with Ubuntu 16.04 installed, and ensure port 80, 22, 443 and 3000 are open. Your react.js application will run on port 3000.

2.  You need to make sure your node server hostname matches it public hostname by running the command below

Now, replace the following:

  • IP-ADDRESS-OR-HOSTNAME to the public IP-address/hostname of your node-server

  • USER with the name of the user on your node-server

  • PATH_TO_YOUR_SSH_KEY with the path to your node-server ssh-key
   chef@workstation:~$ ssh -i PATH_TO_YOUR_SSH_KEY USER@YOUR-IP-ADDRESS-OR-HOSTNAME 'echo YOUR_DOMAIN_NAME | xargs sudo hostname'

3.  To bootstrap your new cloud server to be a node managed by your Chef server, from your workstation, you'll run the command below.

In the following, replace:

  • IP-ADDRESS-OR-HOSTNAME with the public IP-address/hostname of your node-server

  • USER with the name of the user on your node-server

  • PATH_TO_YOUR_SSH_KEY with the path to your node-server ssh-key

  • NODE_NAME with reactJS-node. Understand that NODE_NAME is the name you want to give your node.
    chef@workstation:~$ knife bootstrap IP-ADDRESS-OR-HOSTNAME --connection-user USER --sudo -i PATH_TO_YOUR_SSH_KEY --node-name NODE-NAME
    [] -----> Installing Chef Omnibus (stable/15)
    [] downloading https://omnitruck.chef.io/chef/install.sh
    [] Getting information for chef stable 15 for ubuntu...
    [] Installing chef 15
    [] Thank you for installing Chef Infra Client! For help getting started visit https://learn.chef.io
    [] Starting the first Chef Infra Client Client run...
    [] +---------------------------------------------+
    []  2 product licenses accepted.
    [] +---------------------------------------------+
    [] Starting Chef Infra Client, version 15.0.300
    [] resolving cookbooks for run list: []
    [] Synchronizing Cookbooks:
    [] Installing Cookbook Gems:
    [] Compiling Cookbooks...
    [] [2019-07-01T06:52:36+00:00] WARN: Node reactJS-node has an empty run list.
    [] Converging 0 resources
    [] Running handlers:
    [] Running handlers complete
    [] Chef Infra Client finished, 0/0 resources updated in 02 seconds

Alternatively, run the command below if you are using password as means of authentication to gain access to your server

    chef@workstation:~$ knife bootstrap IP-ADDRESS-OR-HOSTNAME -N NODE_NAME -x USER -P 'PASSWORD' --sudo

4.  To verify that your node has been associated with the Chef server, run the knife node list command.

    chef@workstation:~$ knife node list

You can view the data of your node by running the knife node show command

knife node show NODE-NAME
   chef@workstation:~$ knife node show reactJS-node
   Node Name:   reactJS-node
   Environment: _default
   FQDN:        ip-172-31-56-238.home.internal
   Run List:    
   Platform:    ubuntu 16.04

Building Your React.js Application

With your chef server, workstation and node setup, you are now ready to build your react.js application. You are going to write a cookbook that does the following:

  • Setup and install node.js
  • Install pm2. pm2 is a process manager that helps keep your react.js app alive and running
  • Install the react.js application
  • Start the react.js application

You are going to use the chef execute and bash resource to do that. These resources are both used for running command or script. You'll be using the execute resource to run a single command and the bash resource to run a multi-line command. Feel free to go through the execute and bash resource documentation for more details on its syntax and properties.

Open the default.rb file in the cookbooks/example/attributes/recipes directory on your workstation and replace it with this:

bash 'Install Node.js' do
 cwd "/home/ubuntu"
 code <<-EOH
   curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh
   bash nodesource_setup.sh
   apt-get install nodejs -y 

execute 'Install pm2' do
 cwd "/home/ubuntu"
 command 'npm install pm2 -g'

execute 'Setup react app' do
 cwd "/home/ubuntu"
 command 'npx create-react-app my-app'
 only_if do ! File.exist?('/home/ubuntu/my-app') end

bash 'Start application' do
 cwd "/home/ubuntu"
 code <<-EOH
   cd my-app
   pm2 start npm -- start

In order to run your cookbook, you will have to upload it to the chef-server. Note that each time you make changes to this file, you have to re-upload it. Ensure you are in the react-app-repo directory and run this command:

chef@workstation:~$ knife upload cookbooks/example

You will need to add the cookbook recipe to your node run_list using the command below:

chef@workstation:~$ knife node run_list add reactJS-node 'recipe[example]'
  run_list: recipe[example]

You can check on the documentation for more information on run_list.

Now, you can deploy the cookbook to your reactJS-node node using the knife ssh command.

And you'll want to replace the following:

  • USER with the name of the user on your node-server

  • PATH_TO_YOUR_SSH_KEY with the path to your node-server ssh-key

chef@workstation:~$ knife ssh 'name:reactJS-node' 'sudo chef-client' --ssh-user USER --ssh-identity-file PATH_TO_YOUR_SSH_KEY

You can now access the react.js application by pasting your http://NODE_SERVER_IP_ADDRESS:3000 into a browser window. You should see a page like this one:



This guide provides a flexible foundation on getting started with chef. For more information on Chef, you can refer to the official chef documentation and from learn chef rally.

0 1 1
Share on

Alibaba Clouder

2,605 posts | 745 followers

You may also like