Lighttpd Drupal CMS Clean URL ( SEO ) Rules Set Configuration

Drupal is modular framework and content management system (CMS) and works under Lighttpd too. By default, Drupal passes path arguments to itself via its internally generated URLs. This results in URLs that look like the following: “” This can make URLs hard to read and it also stops many search engines, like Google, from indexing the pages with these URLs.

You can tell Drupal to use “clean URLs”, eliminating the “?q=” in internal URLs. Assuming that your site hosted in rootdirectory itself, open your lighttpd.conf file or domain configuration file:
# vi lighttpd.conf
Make sure mod_rewrite is enabled:
server.modules += ( "mod_rewrite" )
Append following configuration directives:

url.rewrite-final = (
  "^/system/test/(.*)$" => "/index.php?q=system/test/$1",
  "^/system/test-clean-url/(.*)$" => "/index.php?q=system/test-clean-url/$1",
  "/rss.xml$" => "/index.php?q=rss.xml",
  "^/search/(.*)$" => "/index.php?q=search/$1",
  "^/([^.?]*)\?(.*)$" => "/index.php?q=$1&$2",
  "^/([^.?]*)$" => "/index.php?q=$1",
# Error 404
server.error-handler-404  = "/index.php"
# stop these
url.access-deny = ( "~", ".inc", ".engine", ".install", ".module", ".sh", "sql", ".theme", ".tpl.php", ".xtmpl", "Entries", "Repository", "Root" )

Save and close the file. Restart lighttpd, enter:
# /etc/init.d/lighttpd restart
Feel free to adjust rules as per your setup.

Further readings:

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 4 comments so far... add one

CategoryList of Unix and Linux commands
Disk space analyzersdf duf ncdu pydf
File Managementcat cp mkdir tree
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Modern utilitiesbat exa
Network UtilitiesNetHogs dig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg glances gtop jobs killall kill pidof pstree pwdx time vtop
Searchingag grep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
4 comments… add one
  • BlueT Jul 30, 2008 @ 20:48

    Don’t forget to enable mod_rewrite, or you’ll face critical problem 😛

  • 🐧 nixCraft Jul 31, 2008 @ 4:11


    The post has been updated. Appreciate your post.

  • S. Nilesh Aug 8, 2008 @ 18:07

    Vivek, this one is not a good method… exploit drupal internally. Set lighttpd’s 404 handler to /index.php and add the following code in settings.php located in /sites/default/settings.php

    if (strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false) {
        $_lighty_url = $base_url.$_SERVER['REQUEST_URI'];
        $_lighty_url = @parse_url($_lighty_url);
        if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') {
            $_SERVER['QUERY_STRING'] = $_lighty_url['query'];
            parse_str($_lighty_url['query'], $_lighty_query);
            foreach ($_lighty_query as $key => $val)
                $_GET[$key] = $_REQUEST[$key] = $val;
            $_GET['q'] = $_REQUEST['q'] = substr($_lighty_url['path'], 1);

    This doesn’t return a 404 by the server if there exists content. 🙂

  • James Aug 24, 2008 @ 20:31

    Hi .. can someone with expertise in lighty rules please help..I am using Drupal CMS on a LLMP stack and I am stuck on trying

    to come up with rules for a particular module I am wanting to use.

    In lighttpd.conf I have:
    $HTTP[“host”] =~ “(^|.)” {
    server.document-root = “/var/www/public_html/”
    index-file.names = ( “index.php” )
    # for clean urls
    magnet.attract-physical-path-to = (“/etc/lighttpd/rewrite_drupal.lua”)

    In rewrite_drupal.lua I have:
    — little helper function
    function file_exists(path)
    local attr = lighty.stat(path)
    if (attr) then
    return true
    return false
    function removePrefix(str, prefix)
    return str:sub(1,#prefix+1) == prefix..”/” and str:sub(#prefix+2)

    — prefix without the trailing slash

    — If reverting back to production mode comment in the above line and uncomment the line below

    local prefix = ”

    — the magic 😉
    if (not file_exists(lighty.env[“physical.path”])) then
    — file still missing. pass it to the fastcgi backend
    request_uri = removePrefix(lighty.env[“uri.path”], prefix)
    if request_uri then
    lighty.env[“uri.path”] = prefix .. “/index.php”
    local uriquery = lighty.env[“uri.query”] or “”
    lighty.env[“uri.query”] = uriquery .. (uriquery ~= “” and “&” or “”) .. “q=” .. request_uri
    lighty.env[“physical.rel-path”] = lighty.env[“uri.path”]
    lighty.env[“request.orig-uri”] = lighty.env[“request.uri”]
    lighty.env[“physical.path”] = lighty.env[“physical.doc-root”] .. lighty.env[“physical.rel-path”]
    — fallthrough will put it back into the lighty request loop
    — that means we get the 304 handling for free. 😉


    Given the above here is my question :

    I want to know how to enable the following rules for a drupal module called “boost” which tries
    to serve cached html pages bypassing php/drupal and the database. There is a write-up on this

    Now for this Drupal module to work, there are rewrite rules needed. Currently the module author
    has noly provided htaccess rules for Apache. I need lighttpd rules. I have pasted above the rules
    I currently have in lighttpd.conf and rewrite_drupal.lua file. Can someone pls help me with the rules to
    add to the lua or the lighttpd.conf file to make this module work.

    I am pasting below the htaccess rules specific to this module that the author is recommending. If anyone
    has any suggestions on how it can work with lighttpd that would be a big help.

    # Apache htaccess Rewrite rules for static page caching provided by the Boost module:

    Header add Expires “Sun, 19 Nov 1978 05:00:00 GMT”
    Header add Cache-Control “no-store, no-cache, must-revalidate, post-check=0, pre-check=0”

    AddCharset utf-8 .html

    RewriteCond %{REQUEST_METHOD} ^GET$
    RewriteCond %{REQUEST_URI} ^/$
    RewriteCond %{QUERY_STRING} ^$
    RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
    RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0/index.html -f
    RewriteRule ^(.*)$ cache/%{SERVER_NAME}/0/index.html [L]
    RewriteCond %{REQUEST_METHOD} ^GET$
    RewriteCond %{REQUEST_URI} !^/cache
    RewriteCond %{REQUEST_URI} !^/user/login
    RewriteCond %{REQUEST_URI} !^/admin
    RewriteCond %{QUERY_STRING} ^$
    RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
    RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0%{REQUEST_URI} -d
    RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0%{REQUEST_URI}/index.html -f
    RewriteRule ^(.*)$ cache/%{SERVER_NAME}/0/$1/index.html [L]
    RewriteCond %{REQUEST_METHOD} ^GET$
    RewriteCond %{REQUEST_URI} !^/cache
    RewriteCond %{REQUEST_URI} !^/user/login
    RewriteCond %{REQUEST_URI} !^/admin
    RewriteCond %{QUERY_STRING} ^$
    RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
    RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0%{REQUEST_URI}.html -f
    RewriteRule ^(.*)$ cache/%{SERVER_NAME}/0/$1.html [L]

    # Rewrite current-style URLs of the form ‘index.php?q=x’.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Still have questions? Post it on our forum