Setup a Django VM with Vagrant, VirtualBox, and Chef

If you find this post useful, please consider donating in the form of a

If you’ve decided that you want to learn the Django framework, but you don’t know where to begin, you’ve come to the right place. In this guide we’ll be walking step-by-step through the setup of a Django development VM. By the time we’re done we’ll have used a variety of amazing open-source tools to create a virtual machine designed just for Django development.

We’re going to use the following tools in the process:

VirtualBox (download link) This is the virtualization software we will use to run our Django virtual machine. Simply download and install.

Vagrant (download link) Created in 2010 by Mitchell Hashimoto (Twitter) and John Bender (Twitter), Vagrant allows for the programmatic configuration of virtual machines. No longer must we endure the tedious process of clicking around in VirtualBox dialog boxes to configure our VM. We will create a Vagrantfile , a text file which specifies how we want our virtual machine configured, and Vagrant will handle creating and configuring the VM to our specifications. In this tutorial, we’re assuming version 1.02, but as newer versions are released, they should be fine to use as well.

Chef Solo (we’ll download our Chef cookbooks later in this guide) Once Vagrant finishes booting our VM, we need a way to install the various supporting packages (dependencies) that are required to run Django on our virtual machine. We could manually go through this process, but this is the way of the past. Instead, we will download and apply “cookbooks” — collections or abstract definitions as source code that describe how we want our virtual machine to be built — and we’ll apply these cookbooks to our VM immediately after Vagrant finishes booting it up. Don’t worry, it’s not as complicated as it sounds. It actually makes life a lot easier!



Workstation Configuration

The beauty of using a development VM is that very few configuration changes are required on the host workstation. To begin, we’ll want to set up a directory on our machine for use with Vagrant. In this guide we’ll create a django_guide directory in our home directory:

# Create django_guide directory in our home directory mkdir ~/django_guide # Change into the newly created ~/django_guide directory cd ~/django_guide

Once we’re in this directory, we’re going to instruct vagrant to “initialize” this directory. This drops a file called a Vagrantfile in the directory:

# Generate a Vagrantfile in the ~/django_guide directory. vagrant init

If everything worked as planned, the following message should appear:

A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.

Then, we’ll use git (for more information on git , check out Using Git and GitHub to Manage Your Dotfiles) to clone the Chef cookbooks repository from GitHub. We will not need all of the cookbooks downloaded from this repository, but cookbooks don’t take up much space — it’s okay to keep them in case they’re needed in the future.

# Create a place for the Chef cookbooks mkdir ~/django_guide/cookbooks # Change into the newly created ~/django_guide/cookbooks directory cd ~/django_guide/cookbooks # Clone the Chef cookbooks repositories as needed (we will use the following cookbooks in this guide) git clone git://github.com/opscode-cookbooks/apache2.git git clone git://github.com/opscode-cookbooks/apt.git git clone git://github.com/opscode-cookbooks/build-essential.git git clone git://github.com/opscode-cookbooks/git.git git clone git://github.com/opscode-cookbooks/vim.git

At this point the django_guide directory should look like this:

django_guide/ └── Vagrantfile └── cookbooks/ └── apache2/ └── apt/ └── build-essential └── git └── python └── vim

What is a Vagrantfile?

vagrant is controlled completely from the command-line. This is what makes it so powerful. We can manage our VirtualBox VMs without ever leaving our terminal window. The Vagrantfile is a special file that is read by vagrant , and provides instructions about how to provision a virtual machine from scratch. Open the newly created Vagrantfile and edit it to look exactly like this:

Vagrant::Config.run do |config| config.vm.define :djangovm do |django_config| # Every Vagrant virtual environment requires a box to build off of. django_config.vm.box = "lucid64" # The url from where the 'config.vm.box' box will be fetched if it # doesn't already exist on the user's system. django_config.vm.box_url = "http://files.vagrantup.com/lucid64.box" # Forward a port from the guest to the host, which allows for outside # computers to access the VM, whereas host only networking does not. django_config.vm.forward_port 80, 8080 django_config.vm.forward_port 8000, 8001 # Enable provisioning with chef solo, specifying a cookbooks path (relative # to this Vagrantfile), and adding some recipes and/or roles. # django_config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe "apt" chef.add_recipe "apache2::mod_wsgi" chef.add_recipe "build-essential" chef.add_recipe "git" chef.add_recipe "vim" # # # You may also specify custom JSON attributes: # chef.json = { :mysql_password => "foo" } end end end

Let’s take a moment to analyze the above Vagrantfile to see what’s actually going on in it.

django_config.vm.box = "lucid64" – Every virtual machine created with vagrant is based off of something called a base box . This is typically a very minimal image of an operating system without any special customizations applied to it, specifically designed to be used as a foundation. We’ll be using Ubuntu 10.04 “Lucid Lynx” 64-bit as the base box for our Django VM. Here, we’re telling vagrant just that.

– Every virtual machine created with is based off of something called a . This is typically a very minimal image of an operating system without any special customizations applied to it, specifically designed to be used as a foundation. We’ll be using as the base box for our Django VM. Here, we’re telling just that. django_config.vm.box_url = "http://files.vagrantup.com/lucid64.box" – If the base box we want to use hasn’t already been downloaded to our computer, vagrant is smart enough to download it from the Internet, provided we tell it where to look. The address here is the web address where vagrant can find the base box we want to use.

– If the base box we want to use hasn’t already been downloaded to our computer, is smart enough to download it from the Internet, provided we tell it where to look. The address here is the web address where can find the base box we want to use. django_config.vm.forward_port 80, 8080 and config.vm.forward_port 8000, 8001 – These lines set up port forwarding. Port forwarding allows network access to virtual machine ports. In our virtual machine, the Django test server will run on port 8000 by default. Any ports defined here can be accessed from our workstation. Traffic to these ports will get forwarded to our virtual machine. This makes for much quicker and more convenient testing. For example, to access our website, we can open a web browser on our workstation and go to http://localhost:8001 . This request will get forwarded into the virtual machine, where Django will render our website to be sent back and displayed by our web browser.

and – These lines set up port forwarding. Port forwarding allows network access to virtual machine ports. In our virtual machine, the Django test server will run on port by default. Any ports defined here can be accessed from our workstation. Traffic to these ports will get forwarded to our virtual machine. This makes for much quicker and more convenient testing. For example, to access our website, we can open a web browser on our workstation and go to . This request will get forwarded into the virtual machine, where Django will render our website to be sent back and displayed by our web browser. django_config.vm.provision :chef_solo do |chef| – This section loops through the cookbooks and recipes contained within in our cookbooks directory on our workstation. It uses these cookbooks to automatically install and configure all of the listed recipes. For example, chef.add_recipe "vim" installs the vim text editor on our virtual machine.

Starting the Django VM

To start our VM, simply type:

vagrant up

A bunch of interesting stuff will start to scroll by in our terminal. Here’s an excerpt of what we might see after running vagrant up :

[djangovm] Importing base box 'lucid64'... [djangovm] Matching MAC address for NAT networking... [djangovm] Clearing any previously set forwarded ports... [djangovm] Forwarding ports... [djangovm] -- 22 => 2222 (adapter 1) [djangovm] -- 80 => 8080 (adapter 1) [djangovm] -- 8000 => 8001 (adapter 1) [djangovm] Creating shared folders metadata... [djangovm] Clearing any previously set network interfaces... [djangovm] Booting VM... [djangovm] Waiting for VM to boot. This can take a few minutes. [djangovm] VM booted and ready for use! [djangovm] Mounting shared folders... [djangovm] -- v-root: /vagrant [djangovm] -- v-csc-1: /tmp/vagrant-chef-1/chef-solo-1/cookbooks [djangovm] Running provisioner: Vagrant::Provisioners::ChefSolo... [djangovm] Generating chef JSON and uploading... [djangovm] Running chef-solo...

SSH Into the Virtual Machine

To SSH into our djangovm VirtualBox VM, type:

vagrant ssh djangovm

This will drop us a terminal where we can begin to work on the VM. There isn’t much more to do before we have a working Django VM.

Final Steps

Install pip , a Python package installer:

sudo apt-get install python-pip

Install Django using pip :

sudo pip install django

Testing the Django Install

To test our Django install we will start a web server on djangovm , then we’ll try to access it from our host workstation in a web browser. To create and initialize a directory ~/django_project for use with Django and start a web server:

# Change to our home directory cd # Create and initialize a new directory called django_project django-admin.py startproject django_project # Change to the django_project directory cd ~/django_project # Start a web server that is accessible from anywhere python manage.py runserver [::]:8000

This should produce the following output:

Validating models... 0 errors found Django version 1.4, using settings 'django_project.settings' Development server is running at http://[::]:8000/ Quit the server with CONTROL-C.

The Django web server is now running. On our host workstation we should be able to access our Django-powered website by going to http://localhost:8001 . Recall that this works because in our Vagrantfile we set up a port forwarding rule that forwards requests to localhost:8001 to port 8000 on djangovm .

That’s it! Now we’re ready to start developing with Django.

The Django Book is a great resource for getting started!