Navigation

Run a blazing fast website on Lighttpd with WordPress

On a normal shared webspace, an out-of-the-box WordPress installation should be able to serve up to 600k impressions per day. Adding plugins, writing sloppy code, or a badly configured webspace can decrease this dramatically. We are no WordPress fanatics, but like to act platform independent. However, when you and your client finally agreed on a specific platform or framework, be sure to clean up & optimize your work before releasing it into the wild.

This website runs on a FreeBSD VPS (thanks Mischa), with MySQL 5.0.87 and Lighttpd 1.4.23, custom configured to our likings. We use PHP 5.2.11 with FastCGI boosted by the popular eAccelerator, a fork of the Turck MMCache project.

WordPress can be a pain. The Loop is quite heavy on the database, and it can take you some time to find out what code is causing al those MySQL queries. When developing your template, think of what it would need from the database; is it really necessary to load this here?

Disclaimer: tweaking your server can be fun, but this won’t make other optimizations obsolete. You still have to consider your template code to be clean, don’t use large images and try to use sprites when possible. Use CSS multiclasses and reduce your HTTP requests by combining external JavaScript and CSS files.

First, set up Lighttpd to be nice to WordPress. To do this, we need a bunch of modules. Important: beware that the order of the modules here can cause side effects! In lighttpd.conf we used the following:

server.modules = (
"mod_expire",
"mod_redirect",
"mod_alias",
"mod_access",
"mod_auth",
"mod_status",
"mod_fastcgi",
"mod_magnet",
"mod_compress",
"mod_accesslog"
)

mod_expire

To make use of client-side caching you need to understand the browser cache. Adding expire tags to static files will tell your browser to not load a file again from the server when it didn’t change since the last visit. This can improve the browsing experience and reduce page loading time. This is what happens on a page with a bunch of images after setting expire tags:

To add these expire tags to the HTTP header we added the following to httpd.conf:

$HTTP["url"] =~ "\.(png|js|jpg|gif|ico|css)$" {
expire.url = ( "" => "access 40 days" )
}
$HTTP["url"] =~ "\.(html|htm)$" {
expire.url = ( "" => "access 1 seconds" )
}

mod_magnet

For a better URL structure WordPress supports nice permalinks. On an Apache webspace you just set the .htaccess files to behave (and rewrite URLs) in a certain way and your done. On Lighttpd this works a bit different. Back in the days I implemented a working permalinks structure for Drupal, based on this writeup.
WordPress is also dependant on these types of rewrite rules to be able to use permalinks, so we needed a similar approach.

Make sure Lighttpd is able to load the .lua file by adding this:
magnet.attract-physical-path-to = ("/usr/local/etc/wordpress.lua")

Finally, you can download our wordpress.lua here.

mod_compress

To reduce traffic, Lighttpd is able to compress your files before delivering them to the visitor. Most browsers nowadays (yes, Internet Explorer 6 as well) support the Gzip header, so it’s a good idea to make use of this feature. Lighttpd needs a temporary directory for this, so be sure to set this (and fix permissions) before testing:

compress.cache-dir = "/usr/local/www/cache/"
compress.filetype = ("text/plain", "text/html", "text/css", "text/xml", "text/javascript")

eAccelerator

To reduce queries, decrease PHP execution time and serve webpages fast we looked for a intelligent caching system that would lighten the server but still understand the dynamics of externally loaded data (Twitter) or comments. eAccelerator seemed a good fit, but after reading The Murmatrons’ article on their SuperCache plugin we couldn’t wait to have it running on our server. Installing eAccelerator as a Zend extension was a breeze, but setting up PHP took some trial and error. Here are our settings added in PHP.ini:

zend_extension="/usr/local/lib/php/20060613/eaccelerator.so"
eaccelerator.shm_size="32"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="0"
eaccelerator.compress_level="9"
eaccelerator.keys="shm_only"
eaccelerator.allowed_admin_path="/usr/local/www/piwik"

The last variable makes it possible to control eAccelerator from a backend page. From here you can purge the cache, turn it off or on:

You’ll need to copy the PHP file which comes with the eAccelerator build to your webroot for this to work, be sure to set your username & password!

WP SuperCache Plus

To make use of eAccelerators’ caching features but still be able to serve dynamic content we installed WP SuperCache Plus. This plugin is now being maintained from the Murmatrons Trac environment, you can download it there. After installing we are able to tell WordPress to tell which storage engine to use, choose the caching level and modify headers.

Roundup

WordPress isn’t always really code-efficient, but choosing a proper caching and considering environment settings can make a pretty big difference! After setting up your server, be sure to move on to your template code and XHTML, there’s still a lot left to optimize there too!

PS:
All the modification and changes mentioned here in httpd.conf or PHP.ini will require a Lighttpd restart.

Comments

Leave a comment
  • I’ve been looking into using Lighttpd for WordPress today, and then BLAMO! I notice you’ve been doing the same thing. Nice article here, thanks for sharing.

  • That’s cool Stephen, happy to see it helped you. Let us know your findings!

  • Quite a beautiful website. I recently built mine and i was looking for some ideas and you gave me a few. The website was developed by you?

    Thanks

  • Yes, we developed it ourselves. You’re looking at V2 now though :)

  • Thanks Eldora! That’s nice thing to say! haha

  • It’s a custom theme we designed ourselves. At the moment, we (unfortunately), do not have any plans to make the theme publicly available. But if we do, we’ll keep you updated