Run Django with SCGI
This document describe how to run Django with SCGI and how to configure Apache to use it.
Thanks to flup, Django can be run in a separate process and accessed by the web server with SCGI or FastCGI. This possibility is not well documented so this document will present how to do it with Apache.
Prerequisite
First, you need flup, a Python module providing the APIs for SCGI, FastCGI and WSGI. This module is generally named python-flup in the distribution packages.
Next, you need to install and enable mod_scgi and mod_rewrite for Apache.
To enable mod_scgi, you need to create symbolic a symbolic link for the module from apache2/mod-available to apache2/mod-enabled, and then reload apache:
cd /etc/apache2/mods-enabled/ ln -s ../mods-available/scgi.load /etc/init.d/apache2 reload
The method for enabling it is the same as for mod_scgi.
Running Django
The script manage.py can be used to create a SCGI server, you just need to start it with runfcgi. For example:
python manage.py runfcgi protocol=scgi method=prefork host=127.0.0.1 port=40000
You can tweak the configuration with some field when you start the server:
- protocol: scgi, fcgi or ajp
- method: prefork or threaded. Use threaded if the resources are limited or if the server is not under high load
- maxrequests: limit on the number of request served at the same time. Rule of thumb: number of core + 2
Configuring Apache
Finally, you need to configure Apache to connect to Django over SCGI to serve the requests.
Here is an example of my configuration:
<VirtualHost *:80>
ServerName www.linuxcertif.com
ServerAlias www.linuxcertif.com
DocumentRoot /home/linuxcertif/
Alias /media /var/lib/python-support/python2.5/django/contrib/admin/media
SCGIMount /scgi/ 127.0.0.1:40000
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /scgi/$1 [QSA,L,PT]
</VirtualHost>
Let's see what is important here.
First, you need to "mount" the server on a certain path. Here is the line to achieve this:
SCGIMount /scgi/ 127.0.0.1:40000
This says: all access to /scgi/ will be served over SCGI by the server at 127.0.01:4000 (luckily it is the address we had configured for starting the Django application).
Why not mounting the server on the root ("/")? Because we want the static file to be served directly by Apache (much faster). So we use mod_rewrite to redirect the root to SCGI, while still using Apache for static files:
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /scgi/$1 [QSA,L,PT]
And voilà!
Performance
For my configuration, the best performance are achieved with mod_python. However, this method has become a problem because of:
- Security: all my Django applications were running under the same user: www-data. This was also making SELinux totally useless.
- Resource: every instance of Apache is running with an Python interpreter with all the application. This use a lot of ram.
- Because of (2), the static files had to be served by another server (because it was slow to serve them with the bloated apache)
- Some of my Django applications have a slow startup, this was slowing down all the other applications.
- Some oddities of mod_django
To avoid those problems, there is SCGI, FastCGI, AJP, WSGI. With WSGI, the startup time of the interpreter was a problem so SCGI is the best second solution for my configuration.

