Update: I maintain the actually descriptions now in my trac system. See the FCGI+lighty description for Django.
There are different ways to run Django on your machine. One way is only for development: use the
django-admin.py runserver command as documented in the tutorial. The builtin server isn't good for production use, though. The other option is running it with mod_python. This is currently the preferred method to run Django. This posting is here to document a third way: running Django behind lighttpd with FCGI.
First you need to install the needed packages. Fetch them from their respective download address and install them or use preinstalled packages if your system provides those. You will need the following stuff:
- [Django] itself - currently fetched from SVN. Follow the setup instructions or use
python setup.py install.
- [Flup] - a package of different ways to run WSGI applications. I use the threaded WSGIServer in this documentation.
- [lighttpd] itself of course. You need to compile at least the fastcgi, the rewrite and the accesslog module, usually they are compiled with the system.
First after installing ligthttpd you need to create a lighttpd config file. The configfile given here is tailored after my own paths - you will need to change them to your own situation. This config file activates a server on port 8000 on localhost - just like the runserver command would do. But this server is a production quality server with multiple FCGI processes spawned and a very fast media delivery.
# lighttpd configuration file # ############ Options you really have to take care of ####################
server.modules = ( "mod_rewrite", "mod_fastcgi", "mod_accesslog" )
server.document-root = "/home/gb/public_html/" server.indexfiles = ( "index.html", "index.htm", "default.htm" )
these settings attch the server to the same ip and port as runserver would do
server.errorlog = "/home/gb/log/lighttpd-error.log" accesslog.filename = "/home/gb/log/lighttpd-access.log"
fastcgi.server = (
"/myproject-admin.fcgi" => (
"admin" => (
"socket" => "/tmp/myproject-admin.socket",
"bin-path" => "/home/gb/public_html/myproject-admin.fcgi",
"min-procs" => 1,
"max-procs" => 1 ) ),
"/myproject.fcgi" => (
"polls" => (
"socket" => "/tmp/myproject.socket",
"bin-path" => "/home/gb/public_html/myproject.fcgi" ) ) )
url.rewrite = (
This config file will start only one FCGI handler for your admin stuff and the default number of handlers (each one multithreaded!) for your own site. You can finetune these settings with the usual ligthttpd FCGI settings, even make use of external FCGI spawning and offloading of FCGI processes to a distributed FCGI cluster! Admin media files need to go into your lighttpd document root.
The config works by translating all standard URLs to be handled by the FCGI script for each settings file - to add more applications to the system you would only duplicate the rewrite rule for the /polls/ line and change that to choices or whatever your module is named. The next step would be to create the .fcgi scripts. Here are the two I am using:
#!/bin/sh # this is myproject.fcgi - put it into your docroot
#!/bin/sh # this is myproject-admin.fcgi - put it into your docroot
These two files only make use of a django-fcgi.py script. This is not part of the Django distribution (not yet - maybe they will incorporate it) and it's source is given here:
def main(): from flup.server.fcgi import WSGIServer from django.core.handlers.wsgi import WSGIHandler WSGIServer(WSGIHandler()).run()
if name == 'main': main()
As you can see it's rather simple. It uses the threaded WSGIServer from the fcgi-module, but you could as easily use the forked server - but as the lighttpd already does preforking, I think there isn't much use with forking at the FCGI level. This script should be somewhere in your path or just reference it with fully qualified path as I do.
Now you have all parts togehter. I put my lighttpd config into
/home/gb/etc/lighttpd.conf, the .fcgi scripts into
/home/gb/public_html and the django-fcgi.py into
/home/gb/bin. Then I can start the whole mess with
/usr/local/sbin/lighttpd -f etc/lighttpd.conf. This starts the server, preforkes all FCGI handlers and detaches from the tty to become a proper daemon. The nice thing: this will not run under some special system account but under your normal user account, so your own file restrictions apply.
lighttpd+FCGI is quite powerfull and should give you a very nice and very fast option for running Django applications.
- under heavy load some FCGI processes segfault. I first suspected the fcgi library, but after a bit of fiddling (core debugging) I found out it's actually the psycopg on my system that segfaults. So you might have more luck (unless you run Debian Sarge, too)
- Performance behind a front apache isn't what I would have expected. A lighttpd with front apache and 5 backend FCGI processes only achieves 36 requests per second on my machine while the
django-admin.py runserverachieves 45 requests per second! (still faster than mod_python via apache2: only 27 requests per second)
- the separation of the two FCGI scripts didn't work right. Now I don't match only on the .fcgi extension but on the script name, that way /admin/ really uses the myproject-admin.fcgi and /polls/ really uses the myproject.fcgi.
- I have [another document online] that goes into more details with regard to load distribution