Policy as Code with Chef: Mastering Policyfiles

Policy as code (PaC) is a concept that treats infrastructure policies, configurations, and security rules as code artifacts. This approach allows organizations to define, manage, and enforce their policies using the same version control, testing, and continuous integration practices they apply to their software code. 

Managing cookbook dependencies, setting up environments, and giving nodes roles are crucial duties in the realm of Chef Infra. Traditionally, these tasks have been handled separately, requiring multiple artifacts and intricate workflows. However, the introduction of Policyfiles has completely transformed Chef cookbook management.

Policyfiles offer a streamlined approach to creating immutable collections of cookbooks, cookbook dependencies, and attribute configurations. Simple, consistent, and repeatable deployments are made possible by this single document, which is posted to the Chef Infra Server and linked to a set of nodes, empowering organizations to achieve greater efficiency and confidence in their Chef infrastructure. 

In this blog, we will explore the key features and benefits of Policyfiles, shedding light on how a policyfile can be generated, pushed to the Chef Infra server and how it can be applied to a node. We will delve into the concept of Policyfiles, their components, and the advantages they bring to Chef cookbook management. 

With the foundations of Policyfiles and their role in Chef cookbook management in place, let us zoom in on the core of this mechanism: the Policyfile.rb file. 


A Policyfile.rb is a Ruby file in which the run list and cookbook locations are specified. When you generate a cookbook using the latest version of the Chef Workstation, a Policyfile.rb file is automatically created unlike older versions of Chef Workstation/Chef DK that would generate a berksfile. A few older versions of Chef DK also support Policyfiles but the creation of the Policyfile was not automated by default.

To understand the policyfile.rb file, let us take a closer look at its syntax:

Above is an instance of the Policyfile that was automatically generated when the command $ chef generate cookbook apache was executed. 

  • name: This field serves not only as a label for the Policyfile but also replaces the traditional role object. Choose a name that accurately represents the intended function of the systems where the policy will be implemented. 
  • default_source: Indicates the location from which cookbooks are retrieved when they are not explicitly declared in the "cookbook" section. Typically, this refers to a public or private supermarket or the Chef Infra Server. Additionally, default_source can be utilized for an internal repository housing all the organization's cookbooks.
  • run_list: This sets the run list for any nodes using this Policyfile. Run lists are an ordered list of roles and/or recipes that are run in the exact order defined in the run-list; if a recipe appears more than once in the run-list, Chef Infra Client will not run it twice.
  • cookbook `<name>`, path: declares the non-default location where cookbooks can be found.  
To explore the specifics of the syntax, the official documentation on policyfiles.rb provides a comprehensive explanation. 

Follow along these steps to generate a policyfile: 

We shall first generate a policyfile for apache, including a run list followed by generating a policyfile.lock.json file. After which we shall push the lock.json file to the Chef Infra server and apply the policyfile to a node. 

  • In your chef repo, create a separate directory for your policyfiles

          $ mkdir policyfiles 

  • Use the command to generate a file apache.rb 
          $ chef generate policyfile apache 

  • Using the cat apache.rb command, view and modify the policyfile if required and add the path to the apache cookbook. 


Now that we have our Policyfile.rb(apache.rb) we need to generate the Policyfile.lock.json(apache.lock.json) 

The $ chef install <policy_name> command creates the Policyfile.lock.json

Along with this, the install command will find the required cookbooks, build a run-list, and create a local cache. 

Here, replace policy_name with apache.rb 

A Policyfile.lock.json file describes -  

  • The versions of cookbooks in use 
  • A hash of cookbook content
  • The source for all cookbooks
  • Attributes included with the Policyfile 

This file is associated with a revision_id , which is a unique hash that is used to identify versions of the particular policyfile. A new revision_id is generated every time the file is updated or modified.


In practice, at this point you could upload the apache.lock.json to Chef Infra Server, but here is when the concept of policy group comes into play. 

Policy Groups 

When uploading the Policyfile.lock.json to the Chef Infra Server, you can specify a policy group. This policy group serves a similar purpose as an environment, such as production or acceptance, allowing you to group similar servers together. 

A policy group can be understood as a logical division of nodes within a system. For instance, if you have separate environments like Production and Acceptance, you can establish corresponding policy groups. By creating a policy group ‘prod’ and another as ‘acceptance’, you can designate the target location for a specific policyfile's node by pushing it to the respective group. 

Pushing a policyfile to Chef Infra Server

  • The first time you specify a policy group, that policy group name will be instantiated in Chef Infra Server. For instance, Running the command: 
          $ chef push prod apache.lock.json 

Will create the policy group named prod and upload the apache.lock.json to the Chef Infra Server. 

  • Run the command $ chef show-policy to confirm that the policy is on the Chef infra server.
  • Use the $ knife node policy set command to apply the policyfile to a node. 

          $ knife node policy set apache_web prod apache 

  • Now, run the command to connect the linux node with ssh 
          $ knife ssh IPADDRESS –m -x chef -P PWD 'sudo chef-client' 

Note: A node is limited to having a single Policyfile associated with it, this associated file will typically include a run list consisting of multiple cookbooks. Hence, it is not logical for the Policyfile to be confined within a specific cookbook. As a result, we have the flexibility to either utilize the auto generated Policyfile as a reference for creating our own or disregard it entirely. It is recommended to establish a separate "policyfiles" directory at the same level as the "cookbooks" directory, allowing us to generate all our policyfiles conveniently within the designated "policyfiles" directory. 

Learn more about streamlining your cookbook management using policyfiles:



Sarthak Vasal

Sarthak Vasal is a Technical Product Intern at Progress Chef. With a background in computer science, Sarthak brings a blend of technical expertise and business acumen to the table. As part of the Technical Product Marketing team, he is driven by a deep fascination for the journey from an idea to a fully realized product and its market success.