Development Django Box with vagrant and Ubuntu

Vagrant is an open source tool for virtual development enviroments. In this guide we will create an Ubuntu Virtual machine for django development that will be provisioned with chef

VirtualBox Instalation

Prefered virtualization system for vagrant is VirtualBox. It works with another virtualizations tools, you can refer oficial documentation for more information. If you don't have already Virtualbox installed at your local box you can install the package using your package manager:

    $sudo apt-get install virtualbox

Installing Vagrant

My sugestion is not install from package manager, vagrant is a tool that release new version very quickly and always is better get the last version for the oficial website. So go to http://www.vagrantup.com/downloads.html . Choose the version for your system, download it and install it, in my case, i use ubuntu 64 bits:

  $sudo dpkg -i vagrant_1.6.3_x86_64.deb  

Adding a box

Before create an enviroment you need install in your local machine a vagrant box. You can browse Vagrant's Cloud website to find more boxes. For this post we will use an Ubuntu box:

    $ vagrant box add hashicorp/precise64

    Vagrant is upgrading some internal state for the latest version.
    Please do not quit Vagrant at this time. While upgrading, Vagrant
    will need to copy all your boxes, so it will use a considerable
    amount of disk space. After it is done upgrading, the temporary disk
    space will be freed.

    Press ctrl-c now to exit if you want to remove some boxes or free
    up some disk space.

    Press any other key to continue.
    ==> box: Loading metadata for box 'hashicorp/precise64'
        box: URL: https://vagrantcloud.com/hashicorp/precise64
    This box can work with multiple providers! The providers that it
    can work with are listed below. Please review the list and choose
    the provider you will be working with.

    1) hyperv
    2) virtualbox
    3) vmware_fusion
    Enter your choice: 2
    ==> box: Adding box 'hashicorp/precise64' (v1.1.0) for provider: virtualbox
        box: Downloading: https://vagrantcloud.com/hashicorp/precise64/version/2/provider/virtualbox.box
    ==> box: Successfully added box 'hashicorp/precise64' (v1.1.0) for 'virtualbox'!

Create an Ubuntu box Development Environment

You can create a new box in seconds with the command vagrant init and then tell vagrant what kind of box do you want.

    $vagrant init

    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.

This commands creats a file named Vagrantfile. We should edit this file in order to setup our virtualbox according of our needs, so the first step is tell vagrant that we want and ubuntu box editing this file, find the option config.vm.box and editing according the box you want:

    config.vm.box = "hashicorp/precise64"

Up and SSh

    $vagrant up

    Bringing machine 'default' up with 'virtualbox' provider...
    ==> default: Importing base box 'hashicorp/precise64'...
    ==> default: Matching MAC address for NAT networking...
    ==> default: Checking if box 'hashicorp/precise64' is up to date...
    ==> default: Setting the name of the VM: vagrant_default_1407584461236_45519
    ==> default: Clearing any previously set network interfaces...
    ==> default: Preparing network interfaces based on configuration...
        default: Adapter 1: nat
    ==> default: Forwarding ports...
        default: 22 => 2222 (adapter 1)
    ==> default: Booting VM...
    ==> default: Waiting for machine to boot. This may take a few minutes...
        default: SSH address: 127.0.0.1:2222
        default: SSH username: vagrant
        default: SSH auth method: private key
    ==> default: Machine booted and ready!
    ==> default: Checking for guest additions in VM...
        default: The guest additions on this VM do not match the installed version of
        default: VirtualBox! In most cases this is fine, but in rare cases it can
        default: prevent things such as shared folders from working properly. If you see
        default: shared folder errors, please make sure the guest additions within the
        default: virtual machine match the version of VirtualBox you have installed on
        default: your host and reload your VM.
        default: 
        default: Guest Additions Version: 4.2.0
        default: VirtualBox Version: 4.3
    ==> default: Mounting shared folders...
        default: /vagrant => /home/manuel/src/notempo/ntchef/vagrant

    $vagrant ssh
    Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64)

     * Documentation:  https://help.ubuntu.com/
    Welcome to your Vagrant-built virtual machine.
    Last login: Fri Sep 14 06:23:18 2012 from 10.0.2.2

Synced Folders

You can tell vagrant which or your local folders do you want to by synchronized on your virtual machine. In this example we will setup the local directory ~/src/django whre will be a simple django project. In order to setup this directory you have to stop your localbox with vagrant halt and edit Vagrantfile . Find the option config.vm.synced_folder and mofidy it, the first argument is where your local directory is and the second where will be synchronized on the local box:

      config.vm.synced_folder "~/src/django", "/vagrant_data"

Provisioning

Above the list of tools/frameworks/libraries that we need to install in order to setup a django dev box:

  • Python
  • Python virtual env with django framework and postgresql driver
  • Postgresql db
  • Supervisor

Django vagrant chef

Chef is a systems and cloud infrastructure automation framework. You can find an introduction at this link.. We will use chef to provisioning our virtualbox, so everytime that the machine starts, chef will be executed and if there is a change in the infraestructre, cheff will update our box automatically.

Django vagrant chef is a chef project that contains cookboks to setup an ubuntu machine for django development with django/postgresql. You can find the documentation here

    $cd ~/src
    $git clone https://github.com/maigfrga/django-vagrant-chef.git

Django vagrant chef Attributes

Python attributes:

    ['python']['install_method'] = 'package'
    ['python']['venv_dir'] = '/svr/env/'

Postgresql attributes

    ['django_postgresql']['database'] = ''
    ['django_postgresql']['user'] = ''
    ['django_postgresql']['password'] = ''

Packages to be installed on the virtualenv

['django']['python']['packages'] = ["ipdb", "http2"]

Django app details

    ['django']['app']['project_home'] = '/vagrant_data/project'
    ['django']['app']['settings'] = 'project.settings'
    ['django']['app']['port'] = '8080'

Supervisor

    ['supervisor']['inet_username'] = ''
    ['supervisor']['inet_password'] = ''

Configuring vagrant to use Django vagrant chef

Install omnibus plugin that find chef dependencies

  $vagrant plugin install vagrant-omnibus  
  $vagrant plugin install vagrant-librarian-chef

Edit Vagrantfile, setup the location of django-vagran-chef project, and tell vagrant which recipes should be executed:

  config.omnibus.chef_version = :latest
  config.librarian_chef.cheffile_dir = '~/src/django-vagrant-chef'
  config.vm.provision "chef_solo" do |chef|
    chef.cookbooks_path = ["~/src/django-vagrant-chef/cookbooks", "~/src/django-vagrant-chef/site-cookbooks"]
    chef.roles_path = "~/src/django-vagrant-chef/roles"
    chef.data_bags_path = "~/src/django-vagrant-chef/data_bags"
    chef.add_role('django')
      chef.json = {
        "postgresql" => {
          "password" => {
            "postgres" => "iloverandompasswordsbutthiswilldo"
          }
        },
        "python" => {
            "install_method" => "package",
            "venv_dir" => "/svr/env/",
        },
        "django" => {
            "python" => {
                "packages" => ["ipdb", "http2"]
            },
            "app" => {
                "project_home" => "/vagrant_data/project",
                "settings" => "project.settings",
                "port" => "8080"

           }
        },
        "supervisor" => {
            "inet_username" => "manuel",
            "inet_password" => "manuel"
        }
      }
  end

Networking

We will setup a custom ip address for the vagrant box and fordwar the port 80 from our localhost to the port 8080 where the django app is running at the vagrant box. All the docs about vagrant networking at this link

Configuring a private network address

    config.vm.network "private_network", ip: "192.168.33.10"

Reloading box

Every time that you start the vagrant box with vagrant up command, configuration changes are applied, if the vagrant box is already up you can reload configuration with vagran reload --provision

At this link Vagrant file used in this guide

References