Many people have asked for an example for mod_magnet that doesnt involve Ruby on Rails.

I have choosen drupal. Drupal is a nice little content managment platform written in php. I used it before switching to rails. :) Though lets start.

As already mentioned in the “Dr. Magneto vs Mr 404 handler” article, drupal uses a small nice rewrite rule set:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Ok. Lighttpd doesnt support -d/-f. So let’s use mod_magnet. For the example we assume drupal is already installed and accessible under “”. The needed drupal.lua can be downloaded here. The script is nearly as simple as the rails example. So is the integration with lighttpd. The configsnippet is:

$HTTP["url"] =~ "^/drupal" {
    # we only need index.php here.
    index-file.names = ( "index.php" )
    # for clean urls
    magnet.attract-physical-path-to = ( "/etc/lighttpd/drupal.lua" )

Last but not least you need to configure drupal to use clean urls. You go to “Admin” => “Site configuration” => “Clean urls” (quick link ) and click on the “Run the clean URL test” link. If it was successful you can enable clean urls and save the settings.

“But my drupal runs under ‘/someotherpath’, what do i need to change?”

Of course the url conditional in the config snippet above. You also need to change the prefix in the drupal.lua. Do not append a trailing slash there.


404 handler?

Of course it would work as well, but the 404 handler breaks the 403 return code, which is used by drupal.


This is a possible solution aswell. But you need to rewrite all static files to itself.

url.rewrite-once = (
    "^(/drupal/files.*)"       => "$1",
    "^(/drupal/themes.*)"      => "$1",
    "^/drupal/([^.?]*)\?(.*)$" => "/drupal/index.php?q=$1&$2",
    "^/drupal/([^.?]*)$"       => "/drupal/index.php?q=$1",

Killes mentioned another rewrite solution on #drupal on freenode:

url.rewrite-once = (
    "^/drupal/system/test/(.*)$" => "/drupal/index.php?q=system/test/$1",
    "^/drupal/([^.?]*)\?(.*)$"   => "/drupal/index.php?q=$1&$2",
    "^/drupal/([^.?]*)$"         => "/drupal/index.php?q=$1",
    "^/drupal/search/node/(.*)$" => "/drupal/index.php?q=search/node/$1" 


A small side note, in SA-2006-006 the drupal team warned about a security hole through carefully named arbitrary scripts in the files directory. The apache workaround of course doesnt work here either. The following block should secure your server with lighttpd. :)

# "Fix" for Drupal SA-2006-006, requires lighttpd 1.4.13
$HTTP["url"] =~ "^/drupal/files" {
    cgi.assign = ()
    fastcgi.server = ()
    scgi.server = ()

For versions before 1.4.13 you need to move your cgi/fastcgi/scgi defintions into a conditional that inverts the match as shown in the example above. But i have to admit it complicates the config quite a bit. ;)

Update: the script was broken for prefices containing lua patterns special chars. This has been fixed and a new version was uploaded.