There are many different provisioning tools out there, the most popular of which are Chef and Puppet. Chef uses Ruby, Puppet uses a DSL (Domain Specific Language), there are others that use simple bash too, but today we're going to focus on Chef Solo.
To get Chef working properly on your local machine you need a few things.
Make sure you use Ruby 1.9.x and not Ruby 2.x as you will get errors with the json 1.6.1 gem on 2.x. Use rbenv or RVM to manage several different Rubies on the one machine.
You can install dependencies via bundler or manually.
Add following content to new Gemfile
in your future "chef kitchen" (let's say in ~/Projects/chef-demo) and run command bundle install
.
source 'https://rubygems.org'
ruby '1.9.3'
gem 'knife-solo'
gem 'librarian-chef'
Because Chef runs on our server and not on our local machine, we don't need it in our dependencies. So alternativelly you can install gems globally by runnig these commands:
gem install knife-solo --no-ri --no-rdoc
gem install librarian-chef --no-ri --no-rdoc
You can now test your new setup by running knife solo
and you should get output like:
% knife solo
Available solo subcommands: (for details, knife SUB-COMMAND --help)
** SOLO COMMANDS **
knife solo cook [USER@]HOSTNAME [JSON] (options)
knife solo prepare [USER@]HOSTNAME [JSON] (options)
knife solo bootstrap [USER@]HOSTNAME [JSON] (options)
knife solo clean [USER@]HOSTNAME
knife solo init DIRECTORY
And running librarian-chef
which should produce output like:
% librarian-chef
Commands:
librarian-chef clean # Cleans out the cache and install paths.
librarian-chef config # Show or edit the config.
librarian-chef help [COMMAND] # Describe available commands or one specific command
librarian-chef init # Initializes the current directory.
librarian-chef install # Resolves and installs all of the dependencies you specify.
librarian-chef outdated # Lists outdated dependencies.
librarian-chef show # Shows dependencies
librarian-chef update # Updates and installs the dependencies you specify.
librarian-chef version # Displays the version.
Create a new directory structure (i.e. "kitchen") that fits with Chef's standard structure and can be used to build and store recipes.
cd ~/Projects
mkdir chef-demo
cd chef-demo
knife solo init .
The last .
is important. It tells knife-solo that we want to create the project in the current directory. You can change it and place it to another directory. It should create following files and directories structure:
chef-demo/
├── cookbooks
├── data-bags
├── nodes
├── roles
├── site-cookbooks
├── tmp
├── Cheffile
├── Cheffile.lock
├── Gemfile
├── Gemfile.lock
├── solo.rb
Now we have a basic Chef project it’s time to get some cookbooks to install some stuff on our server.
Run librarian-chef init
in the root of your project to make librarian-chef manage it. You should now have a file in the root of your project called Cheffile
. Add there available cookbooks - you can choose from official repository. For example this is Cheffile
for LAMP server.
#!/usr/bin/env ruby
#^syntax detection
site 'http://community.opscode.com/api/v1'
cookbook 'apache2'
cookbook 'mysql'
cookbook 'php'
Now run librarian-chef install
and it should go off and grab your cookbooks and dependencies for you.
Third party cookbooks should always live in ./cookbooks
, so this is where librarian-chef has put them. If you ever need to override something in a cookbook, never modify it, instead, put the corresponding changes in ./site-cookbooks
.
If you want to use git, add cookbooks
and tmp
directories into .gitignore
.
echo /cookbooks >> .gitignore
echo /tmp >> .gitignore
In Digital Ocean a VPS is a droplet. In Chef a VPS or server is called a node. Not surprisingly, node configuration files live in ./nodes
. They should be named in the format {hostname|ip}.json
. Your hostname is probably better long term as your IP address can change. If you don't know either yet, you can call it anything you want, but you will lose a little syntactic sugar on the command-line a little later on.
Before we start bootstraping server try to connect via ssh by calling ssh root@YOUR_SERVER_IP_OR_ALIAS
to check that you're able to make a connection. If everything is OK leave shh by typing exit
.
You can install Chef on a given host by command knife solo prepare root@YOUR_SERVER_IP_OR_ALIAS
. This will login to your server, then download and install chef. It's structured to auto-detect the target OS and change the installation process accordingly. If everything was done correctly you should see similar output like this:
$ knife solo prepare root@YOUR_SERVER_IP_OR_ALIAS
Bootstrapping Chef...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 6516 100 6516 0 0 15228 0 --:--:-- --:--:-- --:--:-- 15931
Downloading Chef for ubuntu...
Installing Chef
(Reading database ... 38511 files and directories currently installed.)
Preparing to replace chef 11.4.4-2.ubuntu.11.04 (using .../tmp.6Bob8rAQ/chef__amd64.deb) ...
Unpacking replacement chef ...
Setting up chef (11.4.4-2.ubuntu.11.04) ...
Thank you for installing Chef!
Now we need to specify which recipes and commands we want to run on server. In case of LAMP the content of our node configuration in file nodes/YOUR_SERVER_IP_OR_ALIAS.json
would be following:
{
"run_list": [
"recipe[apache2]",
"recipe[mysql]",
"recipe[php]"
]
}
Next we need to upload the current kitchen (Chef repo) to the target host and runs chef-solo on that host with our node configuration. This will login to your server, copy across your cookbooks, and then run chef:
$ knife solo cook root@YOUR_SERVER_IP_OR_ALIAS nodes/YOUR_SERVER_IP_OR_ALIAS.json
Once Chef has finished its run open up a browser and visit your IP Address or Hostname for this Droplet and you should see response from Apache server. And that's it! We have basic LAMP server installed.
For better workflow you can use knife solo bootstrap
instead of running knife solo prepare
and then knife solo cook
:
$ knife solo bootstrap root@YOUR_SERVER_IP_OR_ALIAS nodes/YOUR_SERVER_IP_OR_ALIAS.json
knife solo bootstrap
is combination of those two commands and will do all work for us in single command. If something went wrong use parameter -V
for verbose output or -h
for help. For more information about knife solo visit documentation.
We're nearly there. We have a working server and now you need to deploy your application. This might be very specific for your workflow, application and environment so this is place where this tutorial ends.
Basicly you now need to run your app specific commands and configure your environment. For example you if will need to add deployer
user, set his home and rights, you should make site-cookbooks
recipe(s). Usually place it to site-cookbooks/main/recipes/default.rb
and add it into bottom of run_list
of you noce configuration file.
{
"user": {
"name": "deployer",
"password": $PASSWORD
},
"environment": "production",
"run_list": [
"recipe[apache2]",
"recipe[mysql]",
"recipe[php]"
"recipe[main]"
]
}
Nice example of custom site-cookbooks
recipe for set up Ruby on Rails environment with Nginx and Unicorn is in references.