As a Python or Django developer, various WSGI and webservers are available to deploy an application. A very fast, lightweight and relatively easy-to-install solution is the combination of Nginx, the high-performance HTTP server, and uWSGI (see benchmark of python WSGI servers). Furthermore, virtualenv and Fabric are invaluable tools to handle Python dependencies and to automate deployments.
This tutorial describes how to setup a Django 1.3, Nginx and uWSGI stack. My OS at the time of this writing was Ubuntu 10.04 LTS.
Installing all requirements
First install all the handy python tools, if you don't have them already (maybe in your virtualenv):
apt-get install python-virtualenv python-pip fabric
Nginx is not yet in the standard Ubuntu packages, therefore one has to add an additional apt repository:
apt-get install python-software-properties add-apt-repository ppa:nginx/development apt-get update apt-get install nginx
To install uWSGI, activate your virtualenv and install it with pip:
source /path/to/your/virtualenv/bin/activate pip install uwsgi
Configure uWSGI
First you need a WSGI-script for your django project. Put the following file in your django project folder (same folder where settings.py lives) and name it wsgi.py:
import os import sys import site site.addsitedir('/path/to/your/virtualenv/lib/python2.6/site-packages') os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
Then we need an init script for the uWSGI daemon, I used upstart, because I am lazy. The following file should be in /etc/init/uwsgi.conf, for a description of the uWSGI parameters see uWSGI documentation:
# file: /etc/init/uwsgi.conf description "uWSGI starter" start on (local-filesystems and runlevel [2345]) stop on runlevel [016] respawn # home - is the path to our virtualenv directory # pythonpath - the path to our django application # module - the wsgi handler python script exec /path/to/your/virtualenv/bin/uwsgi \ --uid your-user \ --home /path/to/your/virtualenv \ --pythonpath /path/to/your/django/project \ --socket /tmp/uwsgi.sock \ --chmod-socket \ --module wsgi \ --logdate \ --optimize 2 \ --processes 2 \ --master \ --logto /path/to/your/log/uwsgi.log
Be careful to specify the right user (must have all necessary permissions, also for the database) - and no, root is not a good idea.
Configure Nginx
Put the Nginx configuration file for your domain in /etc/nginx/sites-available/yourdomain.com:
# file: /etc/nginx/sites-available/yourdomain.com # nginx configuration for yourdomain.com server { server_name www.yourdomain.com; rewrite ^(.*) http://yourdomain.com$1 permanent; } server { server_name yourdomain.com; access_log /path/to/your/log/access.log; error_log /path/to/your/log/error.log; location / { uwsgi_pass unix:/tmp/uwsgi.sock; include /etc/nginx/uwsgi_params; } location /static { root /root/path/of/your/static/files; } location /media { root /root/path/of/your/media/files; } }
Then activate your domain:
ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/yourdomain.com
Nginx already ships with an init script, so we don't have to write another one.
Starting and Restarting the Server
To start the server type:
start uwsgi /etc/init.d/nginx start
Or if you want to restart it:
restart uwsgi /etc/init.d/nginx restart
And don't forget to set your domain in Django Admin -> Sites!
Deployment with Fabric
Put the following file into /path/to/your/django/project/fabfile.py:
""" Deployment of your django project. """ from fabric.api import * env.hosts = ['yourdomain.com'] env.user = "your-user" def update_django_project(): """ Updates the remote django project. """ with cd('/path/to/your/django/project'): run('git pull') with prefix('source /path/to/your/virtualenv/bin/activate'): run('pip install -r your_pip_requirement_file.txt') run('python manage.py syncdb') run('python manage.py migrate') # if you use south run('python manage.py collectstatic --noinput') def restart_webserver(): """ Restarts remote nginx and uwsgi. """ sudo("service uwsgi restart") sudo("/etc/init.d/nginx restart") def deploy(): """ Deploy Django Project. """ update_django_project() restart_webserver()
Then you can deploy your project with the command:
fab deploy
Further Resources
The following links helped me to get the system running:
- Deploying django projects by Jiri Barton
- Deploying your Django applications with Nginx and uWSGI by Martin Rusev
- Sexy: NGiNX + uWSGI deployment for Django with virtualenv by Many Nights