Wednesday 1 June 2011

Django deployment on Ubuntu 10.04 using nginx and uwsgi

I spend days to figure out how to do this. The problem is that the existing docs are somehow incompelte or too geeky.  So I doccument all the necessary steps that led to a successful deployment, for futre reference. Hopefully this help other beginner uwsgi deployers too!

I used a minimal Ubuntu 10.04 (32bit) so some of the apt-gets mentioned here may not be needed in a normal ubuntu installation.

Prepare the server
apt-get update
apt-get upgrade
apt-get install nano
apt-get install --reinstall language-pack-en
apt-get install libxml2-dev build-essential python-dev python-pip


To import ppa keys you need to:
apt-get install python-software-properties 
Since uwsgi is natively supported from nginx 0.8(?) onward, you need to use the latest nginx package (which is 1.xx) instead of the archaic nginx 0.7x still in debian packages. To install the latest nginx,

sudo su -
echo "deb http://ppa.launchpad.net/nginx/stable/ubuntu lucid main" >> /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
apt-get update 
apt-get install nginx
Now install uwsgi package:


add-apt-repository  ppa:uwsgi/release 
apt-get update
apt-get -y install uwsgi-python



Here is how I organize directories:


/ /www
/dje /proj
/static

So let's install virtualenv and make dje (Django environment)

apt-get install python-virtualenv
mkdir /www
cd /www
virtualenv dje
cd /www/dje
source bin/activate 
  pip install django

Then make a new project called  proj

python /www/dje/bin/django-admin.py startproject proj

cd /www/dje/proj

Dont' forget doing usuasl settings.py stuff and syncdb! Then

mkdir static
nano deploy.py

In the the deploy.py paste:

 import os
import sys
from os.path import abspath, dirname, join
from site import addsitedir
sys.path.insert(0, abspath(join(dirname(__file__), "../")))
from django.conf import settings
os.environ["DJANGO_SETTINGS_MODULE"] = "proj.settings"
# sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))
from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()
You are done with the django side, now make uwsgi configs:

nano /etc/uwsgi-python/apps-available/django.xml 
 And paste in it:


<uwsgi>
    <socket>127.0.0.1:4000</socket>
    <pythonpath>/www/dje</pythonpath>
    <app mountpoint="/">
        <script>wsgihandler</script>
    </app>
</uwsgi>
Then, symlink it:

ln -s /etc/uwsgi-python/apps-available/django.xml /etc/uwsgi-python/apps-enabled/django.xml
Finally make the site's nginx config file:

nano /etc/nginx/sites-available/default

And paste in it:


upstream django {
server 127.0.0.1:4000;
}

server {
listen 80;
server_name mysite.com;

location / {
uwsgi_pass django;
include uwsgi_params;
uwsgi_param UWSGI_PYHOME /www/dje;
uwsgi_param UWSGI_SCRIPT deploy; #the name of deploy.py
# uwsgi_param SCRIPT_NAME django;
uwsgi_param UWSGI_CHDIR /www/dje/proj;
}
location ^~ /media/ {
root /www/dje/proj/static;

}
}

That's it just restart nginx and uwsgi and enjoy the combo:

service uwsgi-python restart
service nginx  restart
And to install mysql :

apt-get install mysql-server 
apt-get install python-mysqldb 
special thanks to Jason Wang and Web2py folks