Howto on nginx, uWSGI and Django
Monday, 17th December 2012, 1939hrs
In the beginning there was Cherokee...
Previously, Cherokee powered this website. Cherokee is a fast server with lots of interesting features. But it lacks a clean, text based configuration file; the full configuration is web based.
Fab is used to deploy this website. It makes it possible to deploy locally (on my laptop), on a staging server (a server I've running) and on production (the server you're connected to now). But it is quite a nuisance to update the configuration parameters of Cherokee on all these environments using a fabfile. So I decided a move from Cherokee was required.
First I've checked several servers, like lighttpd, litespeed and nginx. After trying and checking some reviews and benchmarks I stuck with nginx.
...and FastCGI
When deploying a Django project on a webserver, the server needs to be able to forward the Python requests to a Python environment. There are many gateway protocols, like CGI or FastCGI which do this, but they do have performance drawbacks.
The Python community came up with a standard interface between web servers and a Python environment. It is called WSGI. See PEP 333 and (for Python 3) PEP 3333 for a detailed technical explanation.
There are many implementations of this interface, but after some research I chose for uWSGI.
Then we went for nginx and uWSGI!
In this entry I'll explain how my nginx and uwgsi servers are installed. Hope it is handy for you.
Install nginx and uwsgi
To install nginx on a debian based system:
user@box:~$ sudo apt-get install nginx
To start it and to get its status:
user@box:~$ sudo service nginx start Starting nginx: nginx. user@box:~$ sudo service nginx status * nginx is running
To install uwsgi (and its python plugin) also is very simple process:
user@box:~$ sudo apt-get install uwsgi uwsgi-plugin-python
Configure nginx
To configure nginx to handle your Django website and the related STATIC_ROOT, STATIC_URL, MEDIA_ROOT and URL directories, create this configuration file in /etc/nginx/sites-available.
server { listen 80; server_name elevenbits.com, www.elevenbits.com, elevenbits.org, www.elevenbits.org; access_log /var/log/nginx/elevenbits.access.log; error_log /var/log/nginx/elevenbits.error.log; location /static/ { # STATIC_URL alias /var/www/elevenbits/static/; # STATIC_ROOT expires 30d; } location /media/ { # MEDIA_URL alias /var/www/elevenbits/static/; # MEDIA_ROOT expires 30d; } location / { include uwsgi_params; uwsgi_pass 127.0.0.1:3031; } }
You can name file as you like; I use localhost.conf when nginx runs on my local machine, elevenbits.conf when it runs on production.
I guess you'll understand the configuration file. The only hard part is the "location /" section where a link is given to uWSGI:
Configure uwsgi
The uWSGI starts one (or more) severs which will handle requests from nginx. The interface to these uWSGI servers is specified in the "location /" section of the nginx configuration.
The uWSGI configuration is very simple. This file needs to be placed in /etc/uwsgi/apps-available:
[uwsgi] socket = 127.0.0.1:3031 uid = www-data gid = www-data chdir = /var/www/elevenbits module = elevenbits.uwsgi
You can call this file whatever you like. I just called it django.ini.
Note that you can also specify this file in xml format, or yaml format. See the documentation for detailed information.
Lastly create some symbolic links and restart both servers
user@box:~$ ln -sf /etc/nginx/sites-available/elevenbits.conf /etc/nginx/sites-enabled/elevenbits.conf user@box:~$ ln -sf /etc/uwsgi/apps-available/django.ini /etc/uwsgi/apps-enabled/django.ini
Best to make sure that the default site is removed from the nginx enabled folder. Now, when you restart uwsgi and nginx, your system will be online!