Eric Holscher has recently written an excellent series of articles about provisioning an app server with chef. Around the same time, Gareth Rushgrove mentioned Vagrant - a tool that takes a lot of the pain out of managing development environments on virtual machines.
Stealing with both hands, I present the fewest commands necessary to get a Django app server running in a virtual machine.
- Download & install virtualbox.
- Install vagrant (should just be “
gem install vagrant
“) vagrant box add lucid32 http://files.vagrantup.com/lucid32.box
git clone https://github.com/ericholscher/chef-django-example.git
cd chef-django-example
vagrant init
- edit
Vagrantfile
- Add (or uncomment) these lines:
config.vm.provisioner = :chef_solo config.chef.add_recipe "main" config.chef.json.merge!({ "run_list"=> [ "main::default", "main::python", "main::readthedocs" ], "base_packages"=> ["git-core", "bash-completion"], "users"=> { "docs"=> { "id"=> 1001, "full_name"=> "Docs User", "key"=> "ssh-rsa key-goes-here eric@Bahamut" } }, "groups"=> { "docs"=> { "gid"=> 201, "members"=> ["docs"] } }, "ubuntu_python_packages" => ["python-setuptools", "python-pip", "python-dev", "libpq-dev"], "pip_python_packages" => { "virtualenv" => "1.5.1", "mercurial" => "1.7" }, } )
- edit
cookbooks/main/recipies/default.rb
execute "apt-get update" do action :run end
vagrant up
You now have an app server running the code for Readthedocs. You can’t do a lot with it as this server would need a database and a Celery server to talk to, but you can login and poke at the services:
$ vagrant ssh
vagrant@vagrantup:~$ pgrep gunicorn
vagrant@vagrantup:~$ sudo initctl list
vagrant@vagrantup:~$ sudo tail -f /home/docs/sites/readthedocs.org/run/celery.log
You can’t resolve the names of Holscher’s other servers so you’ll see celery moaning in the logs.
It’s a shame that we don’t end up with a fully-working server to play with, but this still illustrates how easy vagrant and chef make it to build a server. It’s also not difficult to see how this config could be moved into another file in the repository and used to provision staging and production servers as well.
A brief explanation of what’s going on here:
When you run vagrant up
Vagrant reads Vagrantfile,
boots the VM then runs chef-solo to provision it (because you set
config.vm.provisioner = :chef_solo
). Chef follows the
directions in cookbooks/main/recipies/default.rb
to
install the server (because we put the line
config.chef.add_recipe "main"
in
Vagrantfile
). When it’s executing, the data from
config.chef.json
is available in node
- in
Holscher’s examples this data is stored in the node.json
file, though it’s called dna.js
by vagrant (which seems
to be a Chef convention).