Deploy django applications with nginx, uwsgi, virtualenv, south, git and fabric, part 1

deploy django nginx programming virtualenv

You can also be interested in:

After googling for a while, asking my guru and some tests I was able to setup a deploy environment for django projects.

The web server is nginx, the database server mysql, I use uwsgi as wsgi server, all the code is versioned using git, the python libraries are installed in a virtualenv, db migration is assured by South and the deploy is automated using fabric.

While writing this post the whole environment is working but I think it may be adjusted in some ways, so let's take what follows as a guideline to improve in many aspects.

I assume we are working in locale and deploying directly to a production server, ignoring the staging phase.

Installing some packages (locale and remote)

To set up the environment we need python >= 2.6, python-dev, python-setuptools, pip and virtualenv, so (in a debian/ubuntu os):

$ sudo apt-get install python python-dev python-setuptools
$ sudo easy_install pip
$ pip install virtualenv

Ok that's all, the other python packages will be installed in the virtualenv, so now let's continue installing git and mysql

$ sudo apt-get install git
$ sudo apt-get install mysql-server mysql-client
And now it's time to play with nginx.

Installing nginx from source (locale and remote)

Download the source tarball form here, at the time of writing this post the last release is the 1.2.0.

$ tar xvf nginx-1.2.0.tar.gz
$ cd nginx-1.2.0
$ ./configure

Now probably an error occurs saying something like

./configure: error: the HTTP rewrite module requires the PCRE library. You can either disable the module by using --without-http_rewrite_module option, or install the PCRE library into the system, or build the PCRE library statically from the source with nginx by using --with-pcre= option.

Don't worry and let's install some packages more:

$ sudo apt-get install libpcre3 libpcre3-dev

Try again

$ ./configure
$ sudo make
$ sudo make install

If all works as expected you should have nginx web server installed in /usr/local/nginx , you may try if it works by launching

$ sudo /usr/local/nginx/sbin/nginx

Visit http://localhost in locale and you should see a page Welcome to nginx!

Now I think may be useful to create an init script and a folder structure like the debian packaget does.There are three very good pages which explains how to do this, so I give you the links and here we'll see only the code.

Adding the init script

See: http://articles.slicehost.com/2009/3/4/ubuntu-intrepid-adding-an-nginx-init-script

Essentially we have to create a file named nginx in the /etc/init.d directory containing the following code:

#! /bin/sh
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
  . /etc/default/nginx
set -e
. /lib/lsb/init-functions
case "$1" in
    echo -n "Starting $DESC: "
    start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
      --exec $DAEMON -- $DAEMON_OPTS || true
    echo "$NAME."
    echo -n "Stopping $DESC: "
    start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
      --exec $DAEMON || true
    echo "$NAME."
    echo -n "Restarting $DESC: "
    start-stop-daemon --stop --quiet --pidfile \ /usr/local/nginx/logs/$NAME.pid
      --exec $DAEMON || true
    sleep 1
    start-stop-daemon --start --quiet --pidfile \ /usr/local/nginx/logs/$NAME.pid
      --exec $DAEMON -- $DAEMON_OPTS || true
    echo "$NAME."
    echo -n "Reloading $DESC configuration: "
    start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
      --exec $DAEMON || true
    echo "$NAME."
    status_of_proc -p /usr/local/nginx/logs/$NAME.pid "$DAEMON" nginx && exit 0 || exit $?
    echo "Usage: $N {start|stop|restart|reload|force-reload|status}" >&2
    exit 1
exit 0

Now add executable permissions to the file

$ sudo chmod +x /etc/init.d/nginx

You may want to add it to the default runlevel

sudo /usr/sbin/update-rc.d -f nginx defaults

Ok, now you may start, stop and restart nginx webserver:

$ sudo /etc/init.d/nginx start
$ sudo /etc/init.s/nginx stop
$ sudo /etc/init.d/nginx restart

Create package layout

See http://articles.slicehost.com/2009/3/4/ubuntu-intrepid-nginx-from-source-layout

Let's create the sites-available and sites-enabled folders:

$ mkdir /usr/local/nginx/sites-available
$ mkdir /usr/local/nginx/sites-enable

Change the nginx configuration file /usr/local/nginx/conf/nginx.conf including the sites-enabled files

#user nobody
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
  worker_connections 1024;
http {
  include mime.types;
  default_type application/octet-stream;
  #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  # '$status $body_bytes_sent "$http_referer" '
  # '"$http_user_agent" "$http_x_forwarded_for"';
  #access_log logs/access.log main;
  sendfile on;
  #tcp_nopush on;
  #keepalive_timeout 0;
  keepalive_timeout 65;
  #gzip on;
  include /usr/local/nginx/sites-enabled/*;


Then create the default vhost file: /usr/local/nginx/sites-available/default . The file content comes from the original configuration file.

server {
   listen 80;
   server_name localhost;

   #charset koi8-r;

   #access_log logs/host.access.log main;

   location / {
     root html;
     index index.html index.htm;

   #error_page 404 /404.html;

   # redirect server error pages to the static page /50x.html
   error_page 500 502 503 504 /50x.html;
   location = /50x.html {
     root html;

   # proxy the PHP scripts to Apache listening on
   #location ~ \.php$ {
   #  proxy_pass http ://;

   # pass the PHP scripts to FastCGI server listening on
   #location ~ \.php$ {
   #  root html;
   #  fastcgi_pass;
   #  fastcgi_index index.php;
   #  fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
   #  include fastcgi_params;

   # deny access to .htaccess files, if Apache's document root
   # concurs with nginx's one
   #location ~ /\.ht {
   # deny all;


Now just enable the default vhost:

$ ln -s /usr/local/nginx/sites-available/default /usr/local/nginx/sites-enabled/default

and restart nginx

$ sudo /etc/init.d/nginx restart



Continue reading the part 2

Subscribe to abidibo.net!

If you want to stay up to date with new contents published on this blog, then just enter your email address, and you will receive blog updates! You can set you preferences and decide to receive emails only when articles are posted regarding a precise topic.

I promise, you'll never receive spam or advertising of any kind from this subscription, just content updates.

Subscribe to this blog

Comments are welcome!

blog comments powered by Disqus

Your Smartwatch Loves Tasker!

Your Smartwatch Loves Tasker!

Now available for purchase!