How to use Django with FastCGI, SCGI, or AJP
Although
WSGI is the preferred deployment
platform for Django, many people use shared hosting, on which protocols such as
FastCGI, SCGI or AJP are the only viable options.
Essentially, 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 WSGI, FastCGI allows code to stay in memory, allowing requests to be
served with no startup time. While
e.g.
mod_wsgi can either be configured
embedded in the Apache Web server process or as a separate daemon process, a
FastCGI process never runs inside the Web server process, always in a separate,
persistent process.
Prerequisite: flup
Before you can start using FastCGI with Django, you’ll need to install
flup, a
Python library for dealing with FastCGI. Version 0.5 or newer should work fine.
Starting your FastCGI server
FastCGI operates on a client-server model, and in most cases you’ll be starting
the FastCGI process on your own. Your Web server (be it Apache, lighttpd, or
otherwise) only contacts your Django-FastCGI process 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.
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 it can use 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 the
runfcgi command:
If you specify
help as the only option after
runfcgi, it’ll
display a list of all the available options.
You’ll need to specify either a
socket, a
protocol
or both
host and
port. Then, when you set up your
Web server, you’ll just need to point it at the host/port or socket you
specified when starting the FastCGI server. See the
examples, below.
Protocols
Django supports all the protocols that
flup does, namely
fastcgi,
SCGI and
AJP1.3 (the Apache JServ Protocol, version 1.3). Select your preferred
protocol by using the
protocol=<protocol_name> option
with
./manage.py runfcgi – where
<protocol_name> may be one of:
fcgi (the default),
scgi or
ajp. For example:
Examples
Running a threaded server on a TCP port:
Running a preforked server on a Unix domain socket:
Run without daemonizing (backgrounding) the process (good for debugging):
Stopping the FastCGI daemon
If you have the process running in the foreground, it’s easy enough to stop it:
Simply hitting
Ctrl-C will 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
runfcgi, you can
kill the running FastCGI daemon like this:
...where
$PIDFILE is the
pidfile you specified.
To easily restart your FastCGI daemon on Unix, try this small shell script:
Apache setup
To use Django with Apache and FastCGI, you’ll need Apache installed and
configured, with
mod_fastcgi installed and enabled. Consult the Apache
documentation for instructions.
Once you’ve got that set up, point Apache at your Django FastCGI instance by
editing the
httpd.conf (Apache configuration) file. You’ll need to do two
things:
Specifying the location of the FastCGI server
The
FastCGIExternalServer directive tells Apache how to find your FastCGI
server. As the
FastCGIExternalServer docs explain, you can specify either a
socket or a
host. Here are examples of both:
In either case, 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:
Django will automatically use the pre-rewrite version of the URL when
constructing URLs with the
{% url %} template tag (and similar
methods).
Using mod_fcgid as alternative to mod_fastcgi
Another way to serve applications through FastCGI is by using Apache’s
mod_fcgid module. Compared to mod_fastcgi mod_fcgid handles FastCGI
applications differently in that it manages the spawning of worker processes
by itself and doesn’t offer something like
FastCGIExternalServer. This
means that the configuration looks slightly different.
In effect, you have to go the way of adding a script handler similar to what
is described later on regarding running Django in a
shared-hosting
environment. For further details please refer to the
mod_fcgid reference
lighttpd setup
lighttpd is a lightweight Web server commonly used for serving static files. It
supports FastCGI natively and, thus, is a good 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:
Running multiple Django sites on one lighttpd
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:
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.
Cherokee setup
Cherokee is a very fast, flexible and easy to configure Web Server. It
supports the widespread technologies nowadays: FastCGI, SCGI, PHP, CGI, SSI,
TLS and SSL encrypted connections, Virtual hosts, Authentication, on the fly
encoding, Load Balancing, Apache compatible log files, Data Base Balancer,
Reverse HTTP Proxy and much more.
The Cherokee project provides a documentation to
setting up Django with Cherokee.
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.
In your Web root directory, add this to a file named
.htaccess:
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:
This works if your server uses mod_fastcgi. If, on the other hand, you are
using mod_fcgid the setup is mostly the same except for a slight change in the
.htaccess file. Instead of adding a fastcgi-script handler, you have to
add a fcgid-handler:
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 will change. 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:
Forcing the URL prefix to a particular value
Because many of these fastcgi-based solutions require rewriting the URL at
some point inside the Web server, the path information that Django sees may not
resemble the original URL that was passed in. This is a problem if the Django
application is being served from under a particular prefix and you want your
URLs from the
{% url %} tag to look like the prefix, rather than
the rewritten version, which might contain, for example,
mysite.fcgi.
Django makes a good attempt to work out what the real script name prefix
should be. In particular, if the Web server sets the
SCRIPT_URL (specific
to Apache’s mod_rewrite), or
REDIRECT_URL (set by a few servers, including
Apache + mod_rewrite in some situations), Django will work out the original
prefix automatically.
In the cases where Django cannot work out the prefix correctly and where you
want the original value to be used in URLs, you can set the
FORCE_SCRIPT_NAME setting in your main
settings file. This sets the
script name uniformly for every URL served via that settings file. Thus you’ll
need to use different settings files if you want different sets of URLs to
have different script names in this case, but that is a rare situation.
As an example of how to use it, if your Django configuration is serving all of
the URLs under
'/' and you wanted to use this setting, you would set
FORCE_SCRIPT_NAME = '' in your settings file.