See the instructions for deploying a django project on the django deployment page


You’ll need to add the path of your project to the python path just as you did madrona.

Apache Configuration

Using Apache2, you can configure your project as an apache virtual host using the following:

<VirtualHost *:80>

        Alias /media/admin/ /src/django/django/contrib/admin/media/
        <Location /media/admin>
        Order allow,deny
        Allow from all

        Alias /media/ /src/madrona/media/
        <Location /media>
        Order allow,deny
        Allow from all
        Options -ExecCGI
        Options -Indexes

        <Location /media/upload>
        Order Allow,Deny
        Deny from all

        WSGIScriptAlias / /src/project/
        WSGIDaemonProcess project user=gisdev group=gisdev processes=10 threads=1
        WSGIProcessGroup project

WSGIRestrictStdin Off

This file is typically placed in /etc/apache2/sites-available/project and then made available using the apache utilities:

a2ensite project

This configuration allows admin media and standard media to be served by apache. It also locks down the media/upload directory which is where user-uploaded files will be placed; we control access to these files through django views in order to leverage authentication and security.

The wsgi script is a python file similar to this:

#!/usr/bin/env python
import sys
import os

sys.stdout = sys.stderr

# If django is not already in python site-directories

# Project specific

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Nginx/Gunicorn Configuration

nginx is an alternate high-performance, low memory footprint web server. It can use gunicorn to serve django wsgi apps.


With Ubuntu:

sudo apt-get install nginx
sudo pip install gunicorn

# If you use eventlet
sudo pip install eventlet

# or gevent
sudo apt-get install libevent-dev
sudo pip install gevent



worker_processes 1;

user www-data gisdev;

events {
    worker_connections 1024;
    accept_mutex off;

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    gzip on;
    gzip_buffers 32 8k;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    include /etc/nginx/sites-enabled/*;


upstream app_server {
    server localhost:8000 fail_timeout=0;

server {
    access_log /var/log/nginx/app.access.log;
    error_log /var/log/nginx/app.error.log info;
    keepalive_timeout 5;
    client_max_body_size 20M; # file upload size
    root /var/www/;

    location /media/admin {
        alias /usr/local/src/django/django/contrib/admin/media/;

    location /media {
        alias /usr/local/media/app/;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://app_server;


Next start the application server listening on the specified host:port (in this example, localhost:8000). You can technically just run the django development server:

python runserver

But that’s not a good practice for deploying production sites. Instead we can use a gunicorn wsgi server with an asynchronous event handler:

gunicorn_django --log-file=/tmp/app.log -w 3 -k gevent /usr/local/src/project/app/ -u www-data -b --daemon

Finally, in order to ensure that the gunicorn process starts automatically, create an init script; A fairly comprehensive solution for managing multiple gunicorn servers can be found at gunicorn-init. If you need to manage mutiple servers in different virtual environments, take a look at this init script for some ideas.

Table Of Contents

Previous topic


Next topic

Sharing Features and Collections

This Page