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()





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
That’s a pretty nifty solution. Thanks for that. I’ll update my post accordingly once I try it out.
I can’t believe I never looked close enough to the LUA file to realise it bypasses the need for mod_rewrite. Awesome! Thanks.
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.
We are using Lighttpd 1.4. 2.7 seems fine with 1.4.
[...] 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 [...]
Thanks for the lua script. Can I have both LUA and url.rewrite ? Would it clash ?
TIA
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.
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?
[...] 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 [...]
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.
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?
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.