<commit_before>---
layout: documentation
title: Documentation - Provisioners - Chef Solo
---
# Chef Solo Provisioning

[Chef Solo](http://wiki.opscode.com/display/chef/Chef+Solo) allows you to provision your virtual
machine with [Chef Cookbooks](http://wiki.opscode.com/display/chef/Cookbooks) without requiring a
[Chef Server](http://wiki.opscode.com/display/chef/Chef+Server). At a very basic level, [chef](http://www.opscode.com/chef/)
is an open source systems integration framework which automates tasks through programmable "cookbooks."
This page will not go into the details of creating custom chef cookbooks, since that
is covered in detail around the web, but a good place to start is the [opscode cookbooks repository](http://github.com/opscode/cookbooks)
which contains cookbooks for most of the popular server software already made.

## Setting the Cookbooks Path

First, Vagrant needs to know where the cookbooks are located. By default, Vagrant will
look in the "cookbooks" directory relative to the root of the project directory (where
a project's Vagrantfile is). The cookbooks directory should have a structure similar to
the following:

{% highlight bash %}
$ ls cookbooks/
apache2/
passenger_apache2/
rails/
sqlite/
vagrant_main/
{% endhighlight %}

Basically, the cookbooks directory should immediately contain all the folders of the
various cookbooks.

To tell Vagrant what the cookbook path is, set it up in your Vagrantfile, like so:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    # This path will be expanded relative to the project directory
    chef.cookbooks_path = "cookbooks"
  end
end
{% endhighlight %}

<div class="info">
  <h3>Multiple Cookbook Paths</h3>
  <p>
    You can also specify multiple cookbook paths by making the configuration an
    array of file paths. Note that the working directory while running Vagrant will always
    be the directory which contains the Vagrantfile, therefore file paths will always
    be expanded relative to that working directory.

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["cookbooks", "~/company/cookbooks"]
  end
end
{% endhighlight %}
  </p>
</div>

## Configuring the Main Cookbook

By default, Vagrant has an empty run list, or the list of recipes or roles for
Chef to run. We've setup a `vagrant_main` cookbook above which we'll make our
entrypoint. The default recipe for this cookbook is shown below:

{% highlight ruby %}
# vagrant_main cookbook
# This cookbook includes and sets up a server with apache, mysql,
# rails, and passenger.
#
require_recipe "apache2"
require_recipe "mysql"
require_recipe "rails"
require_recipe "passenger_apache2::mod_rails"
{% endhighlight %}

Then, we must tell Vagrant to use this cookbook:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    chef.add_recipe("vagrant_main")
  end
end
{% endhighlight %}

## JSON Configuration

Every chef cookbook has access to the `node` variable which is a hash containing
server-specific configuration options which can be used to control provisioning.
By default, Vagrant JSON configuration looks like the following:

{% highlight ruby %}
{
  :instance_role => "vagrant",
  :vagrant => {
    :config => { ... }, # Full Vagrant config
    :directory => "/vagrant" # Or wherever configured project directory is
  }
}
{% endhighlight %}

This JSON configuration is specifically thought out such that the `instance_role`
key could be used so that cookbooks could be shared between production and development,
possibly tweaking paths or configuration based on the `instance_role`. And
`directory` is useful if you're setting up a VirtualHost for a web server,
for example, and need to set the path to the public directory within your
`directory`.

But sometimes, cookbooks need additional, custom JSON configuration. For this
you can specify additional JSON data in the Vagrantfile:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    # merge is used to preserve the default JSON configuration, otherwise it'll
    # all be overwritten
    chef.json.merge!({
      :load_limit => 42,<commit_msg>Update chef solo JSON accessor<commit_after>---
layout: documentation
title: Documentation - Provisioners - Chef Solo
---
# Chef Solo Provisioning

[Chef Solo](http://wiki.opscode.com/display/chef/Chef+Solo) allows you to provision your virtual
machine with [Chef Cookbooks](http://wiki.opscode.com/display/chef/Cookbooks) without requiring a
[Chef Server](http://wiki.opscode.com/display/chef/Chef+Server). At a very basic level, [chef](http://www.opscode.com/chef/)
is an open source systems integration framework which automates tasks through programmable "cookbooks."
This page will not go into the details of creating custom chef cookbooks, since that
is covered in detail around the web, but a good place to start is the [opscode cookbooks repository](http://github.com/opscode/cookbooks)
which contains cookbooks for most of the popular server software already made.

## Setting the Cookbooks Path

First, Vagrant needs to know where the cookbooks are located. By default, Vagrant will
look in the "cookbooks" directory relative to the root of the project directory (where
a project's Vagrantfile is). The cookbooks directory should have a structure similar to
the following:

{% highlight bash %}
$ ls cookbooks/
apache2/
passenger_apache2/
rails/
sqlite/
vagrant_main/
{% endhighlight %}

Basically, the cookbooks directory should immediately contain all the folders of the
various cookbooks.

To tell Vagrant what the cookbook path is, set it up in your Vagrantfile, like so:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    # This path will be expanded relative to the project directory
    chef.cookbooks_path = "cookbooks"
  end
end
{% endhighlight %}

<div class="info">
  <h3>Multiple Cookbook Paths</h3>
  <p>
    You can also specify multiple cookbook paths by making the configuration an
    array of file paths. Note that the working directory while running Vagrant will always
    be the directory which contains the Vagrantfile, therefore file paths will always
    be expanded relative to that working directory.

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["cookbooks", "~/company/cookbooks"]
  end
end
{% endhighlight %}
  </p>
</div>

## Configuring the Main Cookbook

By default, Vagrant has an empty run list, or the list of recipes or roles for
Chef to run. We've setup a `vagrant_main` cookbook above which we'll make our
entrypoint. The default recipe for this cookbook is shown below:

{% highlight ruby %}
# vagrant_main cookbook
# This cookbook includes and sets up a server with apache, mysql,
# rails, and passenger.
#
require_recipe "apache2"
require_recipe "mysql"
require_recipe "rails"
require_recipe "passenger_apache2::mod_rails"
{% endhighlight %}

Then, we must tell Vagrant to use this cookbook:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    chef.add_recipe("vagrant_main")
  end
end
{% endhighlight %}

## JSON Configuration

Every chef cookbook has access to the `node` variable which is a hash containing
server-specific configuration options which can be used to control provisioning.
By default, Vagrant JSON configuration looks like the following:

{% highlight ruby %}
{
  :instance_role => "vagrant",
  :vagrant => {
    :config => { ... }, # Full Vagrant config
    :directory => "/vagrant" # Or wherever configured project directory is
  }
}
{% endhighlight %}

This JSON configuration is specifically thought out such that the `instance_role`
key could be used so that cookbooks could be shared between production and development,
possibly tweaking paths or configuration based on the `instance_role`. And
`directory` is useful if you're setting up a VirtualHost for a web server,
for example, and need to set the path to the public directory within your
`directory`.

But sometimes, cookbooks need additional, custom JSON configuration. For this
you can specify additional JSON data in the Vagrantfile:

{% highlight ruby %}
Vagrant::Config.run do |config|
  config.vm.provision :chef_solo do |chef|
    # merge is used to preserve the default JSON configuration, otherwise it'll
    # all be overwritten
    chef.json = {
      :load_limit => 42,
{'fraction_non_alphanumeric': 0.07915012841466262, 'fraction_numerical': 0.0018678496381041327, 'mean_word_length': 4.527096774193549, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '945933', 'n_tokens_mistral': 2520, 'n_tokens_neox': 2399, 'n_words': 1051}