Apache to Lighttpd: Wordpress (and Super Cache) rewrite rules

November 22, 2008 at 2:50 pm · Written by Jalada · Filed under Software

x5315 and I have recently moved our blogs to our own VPS hosted at Xen Europe, and due to the limited RAM available (256MB) we decided to experiment with using Lighttpd in place of Apache, because it’s meant to be easier on the RAM and faster – even for dynamic sites like WordPress. Lighttpd is missing a few Apache compatibilities though, and one of the biggest is .htaccess. Lighttpd handles URL rewrites through the ‘mod_rewrite‘ Lighttpd module, and rewrites are added to the main config file (or included in). However mod_rewrite for Lighttpd does not provide the full functionality of Apache rewrites, so instead mod_magnet can be used (even without mod_rewrite, thanks Robert) to perform the rewrites for WordPress.

In order to get working permalinks for WordPress, enable mod_magnet in your Lighttpd config, then create a file called rewrite.lua in your document root (or somewhere accessible) and add the following to it:

attr = lighty.stat(lighty.env["physical.path"])
 
if (not attr) then
  lighty.env["uri.path"] = "/index.php"
  lighty.env["physical.rel-path"] = lighty.env["uri.path"]
  lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
end

What about if you are using WP Super Cache? WP Super Cache requires you to put this in your rewrite.lua file (courtesy of Giovanni Intini):

function serve_html(cached_page)
  if (lighty.stat(cached_page)) then
    lighty.env["physical.path"] = cached_page
    print("Serving cached page: " .. cached_page)
    return true
  else
    return false
  end
end
 
function serve_gzip(cached_page)
  if (lighty.stat(cached_page .. ".gz")) then
    lighty.header["Content-Encoding"] = "gzip"
    lighty.header["Content-Type"] = ""
    lighty.env["physical.path"] = cached_page .. ".gz"
    print("Serving gzipped page: " .. cached_page .. ".gz")
    return true
  else
    return false
  end
end
 
attr = lighty.stat(lighty.env["physical.path"])
 
if (not attr) then
  lighty.env["uri.path"] = "/index.php"
  lighty.env["physical.rel-path"] = lighty.env["uri.path"]
  lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
 
  query_condition = not (lighty.env["uri.query"] and string.find(lighty.env["uri.query"], ".*s=.*"))
  user_cookie = lighty.request["Cookie"] or "no_cookie_here"
  cookie_condition = not (string.find(user_cookie, ".*comment_author.*") or string.find(user_cookie, ".*wordpress.*") or string.find(user_cookie, ".*wp-postpass_.*"))
  if (query_condition and cookie_condition) then
    accept_encoding = lighty.request["Accept-Encoding"] or "no_acceptance"
    cached_page = lighty.env["physical.doc-root"] .. "/wp-content/cache/supercache/" .. lighty.request["Host"] .. lighty.env["request.uri"] .. "/index.html"
    cached_page = string.gsub(cached_page, "//", "/")
    if (string.find(accept_encoding, "gzip")) then
      if not serve_gzip(cached_page) then serve_html(cached_page) end
    else
      serve_html(cached_page)
    end
  end
end

Hefty huh? Once you’ve created the rewrite.lua files, add the following line to your Lighttpd config (adjust accordingly if you put it somewhere other than your document-root):

magnet.attract-physical-path-to = ( server.document-root + "/rewrite.lua" )

With a bit of luck, your rewrites (and WP Super Cache if you are using it, which you should be!) should now work!

You may be worried that having a huge LUA script like that running on every request is going to reduce the effectiveness of wp-super-cache or WordPress in general? Don’t worry, Lighttpd caches the compiled script, it’s pretty swift.

Also, unlike other methods that use mod_rewrite for Lighttpd (which was what was previously on here until I edited it today), you don’t need to add any exceptions for random files in your root directory.

Finally, because this Lua file makes use of a ’stat()’ request, I recommend you optimise stat() calls as best as you can, either by using fam or gamin, or using a fastcgi script in place of stat()

Share:
  • Digg
  • Reddit
  • TwitThis
  • del.icio.us
  • StumbleUpon
  • Technorati
  • Tumblr

14 Responses to “Apache to Lighttpd: Wordpress (and Super Cache) rewrite rules”

  1. Robert says:

    I will add that you don’t need both. I installed WP Super Cache and simply updated my rewrite.lua file to look like the above one. Here is the snipplet that is needed if you don’t use WP Super Cache. You don’t need to use mod_rewrite and it is quite smart. Oh and before you say something there is nothing more to that. You don’t need to do any exceptions to it.

    attr = lighty.stat(lighty.env["physical.path"])

    if (not attr) then
    lighty.env["uri.path"] = “/index.php”
    lighty.env["physical.rel-path"] = lighty.env["uri.path"]
    lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
    end

  2. Robert says:

    Actually I forgot to ask but are you using Lighttpd 1.4 or 1.5? I havn’t compiled or updated to 1.5 yet but I noted some 2.7 functions require 1.5 to work fully.

  3. [...] updated my post on WordPress (and Super Cache) rewrite rules today after receiving a comment from Robert (cheers!) that you don’t need to use mod_rewrite [...]

  4. Humble says:

    Thanks for the lua script. Can I have both LUA and url.rewrite ? Would it clash ?

    TIA

    • Jalada says:

      No, it doesn’t clash, they can be used together. I’m not 100% sure of the order, maybe it depends on when you invoke them in the config. Try it and see.

  5. jacob says:

    i’ve applied the solution above, but it only works on my main page. what can i do to dig in and find out where it’s failing?

  6. [...] have some test reports later this week.  Also, when you run Lighttpd, you will need to refer to this guide on how to do human-friendly permalinks and to work with Super Cache.  There’s also ways to optimize the Lighttpd and MySQL server, which could further enhance [...]

  7. d7 says:

    Like jacob I’m finding that this doesn’t work for my install: It redirects everything to my front page, making articles inaccessible. I couldn’t make sense of the code in the time I had to mess with it, either. I’m guessing that lighttpd and/or WP Super Cache have changed since this rewrite.lua was designed.

    • Jalada says:

      That wouldn’t surprise me to be honest. Unfortunately I’m not actively using my WordPress blog now, so haven’t got the motivation or time to change it.

      That said, my friend x5315 who runs macfanboy.co.uk on the same server as this isn’t having any problems…

    • @d7: We’re still using this script on all our wp installations that run on lighttpd, and it works, so wp-supercache is not the culprit, maybe newer versions of lighttpd broke it?

  8. gomobi says:

    Although Hyper Cache can be used under Lighttpd without extra configuration, it has problem with Mobilepress or other WP mobile plugins. WP super cache works fine with mobilepress, but has compatible problem with Lighttpd. Hope this script will work with my VPS.