The ChefDK on Windows Survival Guide

Intro

The ChefDK is intended to “contain everything you need to start using Chef” and greatly ease the Developer Workstation setup process. Despite the apparent similarities to the Chef Omnibus package, ChefDK users have found a number of issues and inconsistencies, particularly on Windows.



The purpose of this article is to provide users with a better understanding of how ChefDK works and methods for setting up a workstation on Windows while avoiding the common pitfalls.

Differences between ChefDK and the Chef Omnibus Package

AppBundler


Appbundler is a new technology used in the ChefDK to pin Gem version dependencies within executables. It provides similar functionality to bundle exec but loads faster because version constraints do not need to be resolved at runtime.



Appbundler is necessary because often two versions of the same gem must be included in the ChefDK. For example: the chef 12 gem is depended upon for core functionality in ChefDK, but the chef 11 gem is expected by most users and even the chef server itself



The appbundled executables are installed in the ChefDK bin directory, which is /opt/chefdk/bin on Mac/Linux and C:\opscode\chefdk\bin on Windows.



The chef command



The chef command provides many useful functions for ChefDK users:

  • chef exec will correctly call any of the executables from ChefDK’s embedded\bin directory or from the user’s custom installed gems.
  • chef gem is a wrapper to the gem command that will install Ruby gems for use in the ChefDK. Note that they are not installed into /opt/chefdk, but rather in the users ~/.chefdk directory
  • chef shell-init will provide the environment variables to directly use ChefDK’s Ruby and gemset without using chef exec
  • chef verify is used to verify that all components in the Chef development kit are installed correctly
  • chef generate will generate cookbooks, cookbook sub-components (recipes, attributes, lwrps, etc) and even entire repo directories.
  • For more commands (including Policyfile-related) see the documentation

The importance of PATH in ChefDK



At installation time, ChefDK will only expose the executables in /opt/chefdk/bin or C:\opscode\chefdk\bin to the user – these are the aforementioned Appbundled executables. Chef beginners are encouraged to use chef exec to run the executables in the embedded\bin directory.



Experienced Chef Omnibus users typically want to add embedded\bin to the PATH, so that the full suite of ChefDK commands can be run directly from the command line. The correct way to do this is using chef shell-init as noted in the documentation. Unfortunately shell-init support for Windows users is still in the works resulting in quite a bit of confusion and bug reports from getting the order of the bin directories wrong in the PATH.



Another common issue is the existence of both Chef and ChefDK bin directories in the user’s path. Users should only install one or other, not both, as ChefDK is a superset of Omnibus Chef. Uninstall chef-client on your workstation before installing the ChefDK.

ChefDK setup for Powershell users

The correct way to add the embedded\bin executables to your PATH so that you can fully bypass chef exec is by setting the PATH, GEM_ROOT, GEM_HOME and GEM_PATH environment variables like so:

$env:Path += ";$env:USERPROFILE\.chefdk\gem\ruby\2.0.0\bin;c:\opscode\chefdk\embedded\bin"
$env:GEM_ROOT = "c:\opscode\chefdk\embedded\lib\ruby\gems\2.0.0"
$env:GEM_HOME = "$env:USERPROFILE\.chefdk\gem\ruby\2.0.0"
$env:GEM_PATH = "$env:USERPROFILE\.chefdk\gem\ruby\2.0.0;C:\opscode\chefdk\embedded\lib\ruby\gems\2.0.0"

NOTE: ChefDK 0.3.x ships with Ruby 2.0.0. When ChefDK is updated to use a newer Ruby you will need to update 2.0.0 to the new Ruby version



In order to make this permanent you can utilize the Powershell $profile file, equivalent to bash’s profile, to contain the above text block. You can determine the location of the $profile file like so:

PS C:\> echo $profile
C:\Users\Irving Popovetsky\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

PS C:\> echo $profile.AllUsersAllHosts
C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1

For more information, try man about_Profiles.



Before your profile will be run, you must also execute: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force

ChefDK for Bash users

NOTE: The only Windows shell officially supported and recommended by Chef is Powershell. Use Bash at your own risk



There are two popular and fundamentally different Bash implementations for Windows: cygwin and msys. We have found that msys (from the MinGW project) is the better choice for Chef users, particularly because of Path style compatibility between msys and Omnibus Chef. A nice installer is provided by the msysgit project which includes Bash, Git and other essential Unix command-line tools: [http://msysgit.github.io/]



Unfortunately chef shell-init will not produce usable environment variables for Windows for several reasons:

  • The use of Windows-style paths (c:\), where the colon character is used a separator for paths.
  • The lack of quoting for some variables, which breaks if there are any spaces in directory names.

To get this working:

  1. Set the following in your bash profile:
    RUBY_VERSION="2.0.0"
    export PATH="${PATH}:${HOME}/.chefdk/gem/ruby/${RUBY_VERSION}/bin:/c/opscode/chefdk/embedded/bin"
    export GEM_ROOT="/c/opscode/chefdk/embedded/lib/ruby/gems/${RUBY_VERSION}"
    export GEM_HOME="${HOME}/.chefdk/gem/ruby/${RUBY_VERSION}"
    export GEM_PATH="${HOME}/.chefdk/gem/ruby/${RUBY_VERSION}:/c/opscode/chefdk/embedded/lib/ruby/gems/${RUBY_VERSION}"
    
  2. Close and reopen your bash shell. Verify your environment:
    $ chef verify
    Running verification for component 'berkshelf'
    Running verification for component 'test-kitchen'
    Running verification for component 'chef-client'
    Running verification for component 'chef-dk'
    Running verification for component 'chefspec'
    .......................................................................................
    ---------------------------------------------
    Verification of component 'chef-client' succeeded.
    Verification of component 'chefspec' succeeded.
    Verification of component 'berkshelf' succeeded.
    Verification of component 'chef-dk' succeeded.
    Verification of component 'test-kitchen' succeeded.
    

Known major issues on Windows

  • Gems with native extensions cannot be installed into a path with spaces (https://github.com/rubygems/rubygems/issues/523) – This is not only a ChefDK issue, but a general rubygems/Windows issue which impacts users who:
    1. Attempt to install ChefDK into a path with spaces (e.g. ‘C:\Program Files’) or anywhere other than c:\opscode
    2. Attempt to bundle install gems into another project where the path contains spaces (e.g. C:\Users\My User\My Documents\src\cookbook)
  • Gems cannot be installed into a path with a length greater than 260 characters reference
  • Berkshelf SSL errors communicating to supermarket.getchef.com in ChefDK 0.2.0 and 0.3.0 (Fixed in 0.3.2)
    If you’re getting SSL errors when Berkshelf talks to your Chef server, try disabling SSL verification with this Ruby one-liner:
PS C:\Users\Irving Popovetsky> ruby -e "require 'json'; Dir.mkdir('.berkshelf') unless Dir.exists?('.berkshelf') ; File.open('.berkshelf/config.json', 'w+') { |config| config.write(JSON.pretty_generate({ssl: { verify: false }})) }"
Author Irving Popovetsky

Irving leads the Customer Engineering team at Chef

  • Peter Burkholder

    Would this issue regarding Windows PATH separator help address the known issues? https://github.com/opscode/chef-dk/issues/180

  • Boyd Meier

    Thanks – this helps. We really should have a central location for windows tips and tweaks for chef.

  • Thanks for this, I’ve been looking for clarification on this for quite some time. I’m working on a PowerShell script to handle all of this… I’ll post it shortly.

  • Dave Tashner

    How do you use Test Kitchen when the VirtualBox boxes need to be hosted on an internal binary repository with SSL enabled, but with a self-signed certificate? I thought appending the C:opscodechefdkembeddedsslcertscacert.pem file with the root CA cert for the binary repository would work, but Curl is still experiencing SSL errors when attempting to provision my environments using a custom box_url.

  • Other people are happy to have the info it seems, but my first thought was “this blog post should not need to be written”