1 | ==============================
|
---|
2 | How to use Django with FastCGI
|
---|
3 | ==============================
|
---|
4 |
|
---|
5 | While the current preferred setup for running django is Apache_ with
|
---|
6 | `mod_python`_, for many users on shared hosts FastCGI_ is the only viable
|
---|
7 | option. Also, for certain setups FastCGI allows better security and possibly
|
---|
8 | better performance than mod_python.
|
---|
9 |
|
---|
10 | FastCGI is a method of having an external application serve pages to a
|
---|
11 | web-server, via a socket. Like mod_python, FastCGI allows code to stay in
|
---|
12 | memory, thus allowing requests to be served with no start-up time. Unlike
|
---|
13 | mod_python or `mod_perl`_, your fastCGI process does not run inside the
|
---|
14 | web-server process, but runs as a separate persistent process.
|
---|
15 |
|
---|
16 | .. _Apache: http://httpd.apache.org/
|
---|
17 | .. _mod_python: http://www.modpython.org/
|
---|
18 | .. _mod_perl: http://perl.apache.org/
|
---|
19 |
|
---|
20 | .. admonition:: Why run code in a separate process?
|
---|
21 |
|
---|
22 | The traditional ``mod_foo`` trend in apache has various scripting languages
|
---|
23 | (such as PHP, Python, Perl) running inside the process space of your
|
---|
24 | web server. While this does achieve a reduction of start time, it comes
|
---|
25 | at the cost of memory, as every apache process gets its own python
|
---|
26 | interpreter, which will use up a considerable amount of RAM. Due
|
---|
27 | to the nature of FastCGI, it is even possible to have processes which run
|
---|
28 | under a different user as the web server process. On a shared system, this
|
---|
29 | means the ability to further secure your code from other users.
|
---|
30 |
|
---|
31 |
|
---|
32 | Starting your FastCGI server
|
---|
33 | ============================
|
---|
34 |
|
---|
35 | Since FastCGI operates on a client-server model, in most cases you will be starting
|
---|
36 | the FastCGI process on your own. Your webserver (be it Apache, LigHTTPd, or otherwise)
|
---|
37 | will only contact your Django-FastCGI process when it needs a dynamic page to be loaded.
|
---|
38 | Since your daemon is already running with the code in memory, it will be able to serve up
|
---|
39 | the response very quickly.
|
---|
40 |
|
---|
41 | .. admonition:: Note
|
---|
42 |
|
---|
43 | Those who are on shared hosting systems will probably be forced to use
|
---|
44 | webserver-managed FastCGI processes. See the section below on running
|
---|
45 | django with webserver-managed processes for more information on this.
|
---|
46 |
|
---|
47 | There are two ways the Web server can connect to your FastCGI server. It can
|
---|
48 | either use a unix domain socket (named pipe on win32 systems) or it can use a
|
---|
49 | TCP socket. What you choose is a manner of preference; a TCP socket is usually
|
---|
50 | easier due to permissioning issues.
|
---|
51 |
|
---|
52 | To start your server, first change into the directory of your project (wherever
|
---|
53 | your ``manage.py`` is, and then run the manage.py with the runfcgi option::
|
---|
54 |
|
---|
55 | python manage.py runfcgi [options]
|
---|
56 |
|
---|
57 | You can specify ``help`` as the only option after runfcgi, and it will print out
|
---|
58 | a listing of all the available options. You will need to specify either a socket
|
---|
59 | or a host and port.
|
---|
60 |
|
---|
61 | When you set up your web server, you will need to point it at the host/port or
|
---|
62 | socket you chose when starting the FastCGI server.
|
---|
63 |
|
---|
64 | Examples
|
---|
65 | --------
|
---|
66 |
|
---|
67 | Running a threaded server on a TCP port::
|
---|
68 |
|
---|
69 | ./manage.py runfcgi method=threaded host=127.0.0.1 port=3033
|
---|
70 |
|
---|
71 | Running a preforked server on a Unix domain socket::
|
---|
72 |
|
---|
73 | ./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid
|
---|
74 |
|
---|
75 | Run without daemonizing (backgrounding) the process (good for debugging)::
|
---|
76 |
|
---|
77 | ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock
|
---|
78 |
|
---|
79 |
|
---|
80 | Stopping the FastCGI daemon
|
---|
81 | ---------------------------
|
---|
82 |
|
---|
83 | If you have the process running in the foreground, it's easy enough to stop it,
|
---|
84 | simply hitting ``Ctrl-C`` will cause the FastCGI server to exit. However, when
|
---|
85 | we're dealing with background processes, you will need to resort to the unix
|
---|
86 | ``kill`` command.
|
---|
87 |
|
---|
88 | If you specify the ``pidfile`` option to your manage.py runfcgi, you can then kill
|
---|
89 | the running FastCGI daemon like this::
|
---|
90 |
|
---|
91 | kill `cat $PIDFILE`
|
---|
92 |
|
---|
93 | For unix users, to easily restart your FastCGI daemon, this small
|
---|
94 | shell script may be of use::
|
---|
95 |
|
---|
96 | #!/bin/bash
|
---|
97 |
|
---|
98 | PROJDIR="/home/user/myproject"
|
---|
99 | PIDFILE="$PROJDIR/mysite.pid"
|
---|
100 | SOCKET="$PROJDIR/mysite.sock"
|
---|
101 |
|
---|
102 | cd $PROJDIR
|
---|
103 | if [ -f $PIDFILE ]; then
|
---|
104 | kill `cat -- $PIDFILE`
|
---|
105 | rm -f -- $PIDFILE
|
---|
106 | fi
|
---|
107 |
|
---|
108 | exec /usr/bin/env - \
|
---|
109 | PYTHONPATH="../python:.." \
|
---|
110 | ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE
|
---|
111 |
|
---|
112 |
|
---|
113 | Apache Setup
|
---|
114 | ============
|
---|
115 |
|
---|
116 | To configure Django with apache and FastCGI, you must have Apache installed
|
---|
117 | and set up, with mod_fastcgi installed and enabled. Consult your server
|
---|
118 | documentation for doing so.
|
---|
119 |
|
---|
120 | Add the following to your httpd.conf::
|
---|
121 |
|
---|
122 | # Connect to FastCGI via a socket / named pipe
|
---|
123 | FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock
|
---|
124 | # Connect to FastCGI via a TCP host/port
|
---|
125 | # FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033
|
---|
126 |
|
---|
127 | <VirtualHost 64.92.160.91>
|
---|
128 | ServerName mysite.com
|
---|
129 | DocumentRoot /home/user/public_html
|
---|
130 | Alias /media /home/user/python/django/contrib/admin/media
|
---|
131 | RewriteEngine On
|
---|
132 | RewriteRule ^/(media.*)$ /$1 [QSA,L]
|
---|
133 | RewriteCond %{REQUEST_FILENAME} !-f
|
---|
134 | RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
|
---|
135 | </VirtualHost>
|
---|
136 |
|
---|
137 | Note that while you have to specify a mysite.fcgi, that this file doesn't
|
---|
138 | actually have to exist. It is just an internal URL to the webserver which
|
---|
139 | signifies that any requests to that URL will go to the external FastCGI
|
---|
140 | server.
|
---|
141 |
|
---|
142 |
|
---|
143 |
|
---|
144 | LigHTTPd Setup
|
---|
145 | ==============
|
---|
146 |
|
---|
147 | LigHTTPd is a light-weight asynchronous web-server, which is commonly used
|
---|
148 | for serving static files. However, it supports FastCGI natively, and as such
|
---|
149 | is a very good choice for serving both static and dynamic media, if your site
|
---|
150 | does not have any apache-specific components.
|
---|
151 |
|
---|
152 | Make sure ``mod_fastcgi`` is in your modules list, somewhere after
|
---|
153 | mod_rewrite and mod_access, but not after mod_accesslog. You'll probably
|
---|
154 | want mod_alias as well, for serving admin media.
|
---|
155 |
|
---|
156 | Add the following to your lighttpd config file::
|
---|
157 |
|
---|
158 | server.document-root = "/home/user/public_html"
|
---|
159 | fastcgi.server = (
|
---|
160 | "/mysite.fcgi" => (
|
---|
161 | "main" => (
|
---|
162 | # Use host / port instead of socket for TCP fastcgi
|
---|
163 | # "host" => "127.0.0.1",
|
---|
164 | # "port" => 3033,
|
---|
165 | "socket" => "/home/user/mysite.sock",
|
---|
166 | "check-local" => "disable",
|
---|
167 | )
|
---|
168 | ),
|
---|
169 | )
|
---|
170 | alias.url = (
|
---|
171 | "/media/" => "/home/user/django/contrib/admin/media/",
|
---|
172 | )
|
---|
173 |
|
---|
174 | url.rewrite-once = (
|
---|
175 | "^(/media.*)$" => "$1",
|
---|
176 | "^/favicon\.ico$" => "/media/favicon.ico",
|
---|
177 | "^(/.*)$" => "/mysite.fcgi$1",
|
---|
178 | )
|
---|
179 |
|
---|
180 | Running multiple django sites on one LigHTTPd
|
---|
181 | ---------------------------------------------
|
---|
182 |
|
---|
183 | LigHTTPd allows you to use what is called conditional configuration to allow
|
---|
184 | configuration to be customized per-host. In order to specify multiple fastcgi
|
---|
185 | sites, simply add a conditional block around your fastcgi config for each site::
|
---|
186 |
|
---|
187 | $HTTP["host"] == "www.website1.com" {
|
---|
188 | server.document-root = "/foo/site1"
|
---|
189 | fastcgi.server = (
|
---|
190 | ...
|
---|
191 | )
|
---|
192 | ...
|
---|
193 | }
|
---|
194 |
|
---|
195 | $HTTP["host"] == "www.website2.com" {
|
---|
196 | server.document-root = "/foo/site2"
|
---|
197 | fastcgi.server = (
|
---|
198 | ...
|
---|
199 | )
|
---|
200 | ...
|
---|
201 | }
|
---|
202 |
|
---|
203 | You can also run multiple django installations on the same site simply by
|
---|
204 | specifying multiple entries in the ``fastcgi.server`` directive, add one
|
---|
205 | fastcgi host for each.
|
---|
206 |
|
---|
207 |
|
---|
208 | Running Django on a shared-hosting provider
|
---|
209 | ===========================================
|
---|
210 |
|
---|
211 | For many users on shared-hosting providers, you aren't able to run your own
|
---|
212 | server daemons nor do they have access to the httpd.conf of their webserver.
|
---|
213 | However, it is still possible to run Django using webserver-spawned processes.
|
---|
214 |
|
---|
215 |
|
---|
216 | .. admonition:: Note
|
---|
217 |
|
---|
218 | If you are using webserver-managed processes, there's no need for you
|
---|
219 | to start the FastCGI server on your own. Apache will spawn a number
|
---|
220 | of processes, scaling as it needs to.
|
---|
221 |
|
---|
222 |
|
---|
223 | In your web root directory, add this to a file named .htaccess ::
|
---|
224 |
|
---|
225 | AddHandler fastcgi-script .fcgi
|
---|
226 | RewriteEngine On
|
---|
227 | RewriteCond %{REQUEST_FILENAME} !-f
|
---|
228 | RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
|
---|
229 |
|
---|
230 |
|
---|
231 | Now you must add a small shim script in order for apache to properly
|
---|
232 | spawn your FastCGI program. Create a mysite.fcgi and place it in your
|
---|
233 | web directory, making it executable ::
|
---|
234 |
|
---|
235 | #!/usr/bin/python
|
---|
236 | import sys, os
|
---|
237 |
|
---|
238 | # add a custom pythonpath
|
---|
239 | sys.path.insert(0, "/home/user/python")
|
---|
240 |
|
---|
241 | # switch to the directory of your project. (optional)
|
---|
242 | # os.chdir("/home/user/myproject")
|
---|
243 |
|
---|
244 | # change to the name of your app's settings module
|
---|
245 | os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
|
---|
246 |
|
---|
247 | from django.core.servers.fastcgi import runfastcgi
|
---|
248 | runfastcgi(["method=threaded", "daemonize=false"])
|
---|
249 |
|
---|
250 |
|
---|
251 | Restarting the spawned server
|
---|
252 | -----------------------------
|
---|
253 |
|
---|
254 | If you change the code of your site, to make apache re-load your django
|
---|
255 | application, you do not need to restart the server. Simply re-upload or
|
---|
256 | edit your ``mysite.fcgi`` in such a way that the timestamp on the file
|
---|
257 | will change. When apache sees that the file has been updated, it will
|
---|
258 | restart your django application for you.
|
---|
259 |
|
---|
260 | If you have access to a command shell on a unix system, restarting the
|
---|
261 | server can be done with the ``touch`` command::
|
---|
262 |
|
---|
263 | touch mysite.fcgi
|
---|