Using Django with FastCGI

Although Django under Apache and mod_python is the most robust deployment setup, many people use shared hosting, on which FastCGI is the only available deployment option. Additionally, in some situations, FastCGI allows better security and possibly better performance than mod_python. For small sites, FastCGI can also be more lightweight than Apache.

FastCGI Overview – FastCGI is an efficient way of letting an external application serve pages to a Web server. The Web server delegates the incoming Web requests (via a socket) to FastCGI, which executes the code and passes the response back to the Web server, which, in turn, passes it back to the client’s Web browser. Like mod_python, FastCGI allows code to stay in memory, allowing requests to be served with no startup time. Unlike mod_python, a FastCGI process doesn’t run inside the Web server process, but in a separate, persistent process.

Why Run Code in a Separate Process? – The traditional mod_* arrangements in Apache embed various scripting languages (most notably PHP, Python/mod_python, and Perl/mod_perl) inside the process space of your Web server. Although this lowers startup time (because code doesn’t have to be read off disk for every request), it comes at the cost of memory use.

Each Apache process gets a copy of the Apache engine, complete with all the features of Apache that Django simply doesn’t take advantage of. FastCGI processes, on the other hand, only have the memory overhead of Python and Django. Due to the nature of FastCGI, it’s also possible to have processes that run under a different user account than the Web server process. That’s a nice security benefit on shared systems, because it means you can secure your code from other users.

Before you can start using FastCGI with Django, you’ll need to install flup, a Python library for dealing with FastCGI. Some users have reported stalled pages with older flup versions, so you may want to use the latest SVN version. Get flup at http://www.djangoproject.com/r/flup/.

Running Your FastCGI Server – FastCGI operates on a client/server model, and in most cases you’ll be starting the FastCGI server process on your own. Your Web server (be it Apache, lighttpd, or otherwise) contacts your Django-FastCGI process only when the server needs a dynamic page to be loaded. Because the daemon is already running with the code in memory, it’s able to serve the response very quickly.

Note – If you’re on a shared hosting system, you’ll probably be forced to use Web server-managed FastCGI processes. If you’re in this situation, you should read the section titled “Running Django on a Shared-Hosting Provider with Apache,” below.

A Web server can connect to a FastCGI server in one of two ways: it can use either a Unix domain socket (a named pipe on Win32 systems) or a TCP socket. What you choose is a manner of preference; a TCP socket is usually easier due to permissions issues. To start your server, first change into the directory of your project (wherever your manage.py is), and then run manage.py with the runfcgi command:

./manage.py runfcgi [options]

If you specify help as the only option after runfcgi, a list of all the available options will display. You’ll need to specify either a socket or both host and port. Then, when you set up your Web server, you’ll just need to point it at the socket or host/port you specified when starting the FastCGI server. A few examples should help explain this:

  • Running a threaded server on a TCP port:

./manage.py runfcgi method=threaded host=127.0.0.1 port=3033

  • Running a preforked server on a Unix domain socket:

./manage.py runfcgi method=prefork socket=/home/user/mysite.sock    pidfile=django.pid

  • Run without daemonizing (backgrounding) the process (good for debugging):

./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock

Stopping the FastCGI Daemon – If you have the process running in the foreground, it’s easy enough to stop it: simply press Ctrl+C to stop and quit the FastCGI server. However, when you’re dealing with background processes, you’ll need to resort to the Unix kill command. If you specify the pidfile option to your manage.py runfcgi, you can kill the running FastCGI daemon like this:

kill `cat $PIDFILE`

where $PIDFILE is the pidfile you specified. To easily restart your FastCGI daemon on Unix, you can use this small shell script:

#!/bin/bash
# Replace these three settings.
PROJDIR=”/home/user/myproject”
PIDFILE=”$PROJDIR/mysite.pid”
SOCKET=”$PROJDIR/mysite.sock”

cd $PROJDIR
if [ -f $PIDFILE ]; then
kill `cat — $PIDFILE`
rm -f — $PIDFILE
fi

exec /usr/bin/env – \
PYTHONPATH=”../python:..” \
./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE

Using Django with Apache and FastCGI – To use Django with Apache and FastCGI, you’ll need Apache installed and configured, with mod_fastcgi installed and enabled. Consult the Apache and mod_fastcgi documentation for instructions: http://www.djangoproject.com/r/mod_fastcgi/. Once you’ve completed the setup, point Apache at your Django FastCGI instance by editing the httpd.conf (Apache configuration) file. You’ll need to do two things:

  •  Use the FastCGIExternalServer directive to specify the location of your FastCGI server.
  • Use mod_rewrite to point URLs at FastCGI as appropriate.

Specifying the Location of the FastCGI Server – The FastCGIExternalServer directive tells Apache how to find your FastCGI server. As the FastCGIExternalServer docs (http://www.djangoproject.com/r/mod_fastcgi/FastCGIExternalServer/) explain, you can specify either a socket or a host. Here are examples of both:

# Connect to FastCGI via a socket/named pipe:
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock

# Connect to FastCGI via a TCP host/port:
FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033

In either case, the the directory /home/user/public_html/ should exist, though the file /home/user/public_html/mysite.fcgi doesn’t actually have to exist. It’s just a URL used by the Web server internally — a hook for signifying which requests at a URL should be handled by FastCGI. (More on this in the next section.)

Using mod_rewrite to Point URLs at FastCGI – The second step is telling Apache to use FastCGI for URLs that match a certain pattern. To do this, use the mod_rewrite module and rewrite URLs to mysite.fcgi (or whatever you specified in the FastCGIExternalServer directive, as explained in the previous section). In this example, we tell Apache to use FastCGI to handle any request that doesn’t represent a file on the filesystem and doesn’t start with /media/. This is probably the most common case, if you’re using Django’s admin site:

<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L] </VirtualHost>

FastCGI and lighttpd – lighttpd (http://www.djangoproject.com/r/lighttpd/) is a lightweight Web server commonly used for serving static files. It supports FastCGI natively and thus is also an ideal choice for serving both static and dynamic pages, if your site doesn’t have any Apache-specific needs. Make sure mod_fastcgi is in your modules list, somewhere after mod_rewrite and mod_access, but not after mod_accesslog. You’ll probably want mod_alias as well, for serving admin media. Add the following to your lighttpd config file:

server.document-root = “/home/user/public_html”
fastcgi.server = (
“/mysite.fcgi” => (
“main” => (
# Use host / port instead of socket for TCP fastcgi
# “host” => “127.0.0.1”,
# “port” => 3033,
“socket” => “/home/user/mysite.sock”,
“check-local” => “disable”,
)
),
)
alias.url = (
“/media/” => “/home/user/django/contrib/admin/media/”,
)

url.rewrite-once = (
“^(/media.*)$” => “$1”,
“^/favicon\.ico$” => “/media/favicon.ico”,
“^(/.*)$” => “/mysite.fcgi$1”,
)

Running Multiple Django Sites on One lighttpd Instance – lighttpd lets you use “conditional configuration” to allow configuration to be customized per host. To specify multiple FastCGI sites, just add a conditional block around your FastCGI config for each site:

# If the hostname is ‘www.example1.com’…
$HTTP[“host”] == “www.example1.com” {
server.document-root = “/foo/site1”
fastcgi.server = (

)

}

# If the hostname is ‘www.example2.com’…
$HTTP[“host”] == “www.example2.com” {
server.document-root = “/foo/site2”
fastcgi.server = (

)

}

You can also run multiple Django installations on the same site simply by specifying multiple entries in the fastcgi.server directive. Add one FastCGI host for each.

Running Django on a Shared-Hosting Provider with Apache – Many shared-hosting providers don’t allow you to run your own server daemons or edit the httpd.conf file. In these cases, it’s still possible to run Django using Web server-spawned processes.

Note – If you’re using Web server-spawned processes, as explained in this section, there’s no need for you to start the FastCGI server on your own. Apache will spawn a number of processes, scaling as it needs to. In your Web root directory, add this to a file named .htaccess

AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

Then, create a small script that tells Apache how to spawn your FastCGI program. Create a file, mysite.fcgi, and place it in your Web directory, and be sure to make it executable

#!/usr/bin/python
import sys, os
# Add a custom Python path.
sys.path.insert(0, “/home/user/python”)
# Switch to the directory of your project. (Optional.)
# os.chdir(“/home/user/myproject”)
# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ[‘DJANGO_SETTINGS_MODULE’] = “myproject.settings”

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method=”threaded”, daemonize=”false”)

Restarting the Spawned Server – If you change any Python code on your site, you’ll need to tell FastCGI the code has changed. But there’s no need to restart Apache in this case. Rather, just reupload mysite.fcgi — or edit the file — so that the timestamp on the file changes. When Apache sees the file has been updated, it will restart your Django application for you.
If you have access to a command shell on a Unix system, you can accomplish this easily by using the touch command:

touch mysite.fcgi

Back to Tutorial

Performance Tuning
Security Considerations

Get industry recognized certification – Contact us

keyboard_arrow_up