============================== How to use Django with FastCGI ============================== While the current preferred setup for running django is Apache_ with `mod_python`_, for many users on shared hosts FastCGI_ is the only viable option. Also, for certain setups FastCGI allows better security and possibly better performance than mod_python. FastCGI is a method of having an external application serve pages to a web-server, via a socket. Like mod_python, FastCGI allows code to stay in memory, thus allowing requests to be served with no start-up time. Unlike mod_python or `mod_perl`_, your fastCGI process does not run inside the web-server process, but runs as a separate persistent process. .. _Apache: http://httpd.apache.org/ .. _mod_python: http://www.modpython.org/ .. _mod_perl: http://perl.apache.org/ .. admonition:: Why run code in a separate process? The traditional ``mod_foo`` trend in apache has various scripting languages (such as PHP, Python, Perl) running inside the process space of your web server. While this does achieve a reduction of start time, it comes at the cost of memory, as every apache process gets its own python interpreter, which will use up a considerable amount of RAM. Due to the nature of FastCGI, it is even possible to have processes which run under a different user as the web server process. On a shared system, this means the ability to further secure your code from other users. Starting your FastCGI server ============================ Since FastCGI operates on a client-server model, in most cases you will be starting the FastCGI process on your own. Your webserver (be it Apache, LigHTTPd, or otherwise) will only contact your Django-FastCGI process when it needs a dynamic page to be loaded. Since your daemon is already running with the code in memory, it will be able to serve up the response very quickly. .. admonition:: Note Those who are on shared hosting systems will probably be forced to use webserver-managed FastCGI processes. See the section below on running django with webserver-managed processes for more information on this. There are two ways the Web server can connect to your FastCGI server. It can either use a unix domain socket (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 permissioning issues. To start your server, first change into the directory of your project (wherever your ``manage.py`` is, and then run the manage.py with the runfcgi option:: python manage.py runfcgi [options] You can specify ``help`` as the only option after runfcgi, and it will print out a listing of all the available options. You will need to specify either a socket or a host and port. When you set up your web server, you will need to point it at the host/port or socket you chose when starting the FastCGI server. Examples -------- 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 hitting ``Ctrl-C`` will cause the FastCGI server to exit. However, when we're dealing with background processes, you will need to resort to the unix ``kill`` command. If you specify the ``pidfile`` option to your manage.py runfcgi, you can then kill the running FastCGI daemon like this:: kill `cat $PIDFILE` For unix users, to easily restart your FastCGI daemon, this small shell script may be of use:: #!/bin/bash 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 Apache Setup ============ To configure Django with apache and FastCGI, you must have Apache installed and set up, with mod_fastcgi installed and enabled. Consult your server documentation for doing so. Add the following to your httpd.conf:: # 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 ServerName mysite.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] Note that while you have to specify a mysite.fcgi, that this file doesn't actually have to exist. It is just an internal URL to the webserver which signifies that any requests to that URL will go to the external FastCGI server. LigHTTPd Setup ============== LigHTTPd is a light-weight asynchronous web-server, which is commonly used for serving static files. However, it supports FastCGI natively, and as such is a very good choice for serving both static and dynamic media, if your site does not have any apache-specific components. 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 --------------------------------------------- LigHTTPd allows you to use what is called conditional configuration to allow configuration to be customized per-host. In order to specify multiple fastcgi sites, simply add a conditional block around your fastcgi config for each site:: $HTTP["host"] == "www.website1.com" { server.document-root = "/foo/site1" fastcgi.server = ( ... ) ... } $HTTP["host"] == "www.website2.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 =========================================== For many users on shared-hosting providers, you aren't able to run your own server daemons nor do they have access to the httpd.conf of their webserver. However, it is still possible to run Django using webserver-spawned processes. .. admonition:: Note If you are using webserver-managed processes, 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] Now you must add a small shim script in order for apache to properly spawn your FastCGI program. Create a mysite.fcgi and place it in your web directory, making it executable :: #!/usr/bin/python import sys, os # add a custom pythonpath sys.path.insert(0, "/home/user/python") # switch to the directory of your project. (optional) # os.chdir("/home/user/myproject") # change to the name of your app's settings module 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 the code of your site, to make apache re-load your django application, you do not need to restart the server. Simply re-upload or edit your ``mysite.fcgi`` in such a way that the timestamp on the file will change. When apache sees that 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, restarting the server can be done with the ``touch`` command:: touch mysite.fcgi