Deploying Django projects

Posted on March 16, 2011

Nothing of this would have been easy without a modern and decent environment. I have found it in Ubuntu. Also, let me assume you can run django-admin.py runserver in the virtualenv and it works.

Requirements

  • dedicated hosting (or VPS) with root access
  • Ubuntu 10.10 Maverick (do not use 10.04 if you can)
  • virtualenv with your project, able to run runserver

Tools of the trade

Seriously, forget about Apache for its complicated configuration. Supervisord is a much better option for managing Django projects than uwsgi init scripts found in Ubuntu.

add-apt-repository ppa:nginx/development
add-apt-repository ppa:chris-lea/uwsgi
apt-get install ubuntu uwsgi-python2.6 supervisor

Configure the Django project

Let me assume

  • your username is uvar
  • your home directory is /home/uvar
  • your virtualenvs are located in /home/uvar/envs
  • your virtualenv for the project is in /home/uvar/envs/uvar
  • your project has been checked out to /home/uvar/uvar.si

Create the following directories which will hold logs, sockets, and static files in your virtualenv:

mkdir /home/uvar/envs/uvar/{logs,run,static}
chown -R uvar. /home/uvar/envs/uvar

Configure Nginx

Look at how easy is to set up a site in Nginx. Put this to your /etc/nginx/sites-enabled/<domain>. I will configure the site http://uvar.si:

server {
        server_name *.uvar.si;
        rewrite ^ http://uvar.si$request_uri permanent;
}

server {
        server_name uvar.si;

        location / {
                uwsgi_pass unix:/home/uvar/envs/uvar/run/uwsgi.sock;
                include /etc/nginx/uwsgi_params;
        }

        location /static {
                root /home/uvar/envs/uvar;
        }
}

The first section redirects everything to uvar.si (like www.uvar.si to uvar.si).

Next, location / is passing everything to our Django project via socket.

Last, location /static serves everything from the directory which has collected media using the command django-admin.py collectstatic some time earlier.

Configure uwsgi/supervisord

Put the following config file into /etc/supervisor/conf.d/uvar.si.conf:

[program:uvar.si]
command=uwsgi-python2.6
        --socket /home/uvar/envs/uvar/run/uwsgi.sock
        --chmod-socket
        --processes 2
        --master
        --home /home/uvar/envs/uvar
        --module django.core.handlers.wsgi:WSGIHandler()
environment=DJANGO_SETTINGS_MODULE='cookbook.settings'
user=uvar
autostart=true
autorestart=true
stdout_logfile=/home/uvar/envs/uvar/log/uwsgi.log
stderr_logfile=/home/uvar/envs/uvar/log/uwsgi.err
stopsignal=QUIT

Restart (start or stop) with supervisorctl restart uvar.si. That's it! Your site should be up and running now. Easy, wasn't it?

Bonus: deploying with Fabric

Allow access to everyone in supervisord in /etc/supervisor/supervisord.conf:

chmod=0777

Restart supervisord. Activate the virtualenvwrapper in your .bashrc on the hosting. Put the following two lines somewhere at the beginning of .bashrc, before the line [ -z "$PS1" ] && return:

export WORKON_HOME=~/envs
. /usr/local/bin/virtualenvwrapper.sh

Install the fresh fabric into your ordinary (development system) with pip:

pip install fabric

Now, create the fabfile.py:

from fabric.operations import run
from fabric.decorators import hosts
from fabric.context_managers import cd, prefix

@hosts('uvar@uvar.si')
def deploy():
    with cd('~/uvar.si'):
        run('git pull')
    with prefix('workon uvar'):
        run('django-admin.py syncdb')
        run('django-admin.py collectstatic --noinput')
    run('supervisorctl restart uvar.si')

Now you can deploy your project with

fab deploy