How to move a wordpress multisite to a new “folder”

Moving a wordpress multisite (a SINGLE site, not an entire install) to a new subfolder (not really a folder as it’s virtual, but whatever) is not hard, but it’s also not as easy as it should be. Here are the steps I took:

  1. Change the site path from the Network Admin backend, and be sure to have it update “siteurl” and “home”. Make a note of the siteid while you’re here, which you can deduce from the “id=” parameter in the URL.
  2. Regenerate the permalinks from the “Settings -> Permalinks” menu – I just temporarily switch the permalink structure to something else and right back again to the original settings – there’s probably a more elegant way. If you’re using a custom structure, be sure to note it before you change as it won’t be retained in the text field.
  3. Fix all the links inside the content – I just used a mysql “update”, like this:
    update wp_<your multisite blog id>_posts set post_content = replace(post_content,’/oldpath/’,’/newpath/’);
    For bonus points, you can create a backup as a temporary table before the replace. Be aware this backup table will go away after you terminate your mysql connection.
    create temporary table wp_<your multisite blog id>_posts_tmp select * from wp_<your multisite blog id>_posts;
    This should fix all embedded media and page links – but you’ll still need to test, obviously.
  4. Clear your object / apc caches by restarting apache and doing whatever else you need to clear your object cache backend. Since we’re directly editing mysql tables, the object cache doesn’t get the clues it needs to decache stale values and you can get weird issues. If you’ve got a frontend page cache, clear that too.

These steps have worked fine here, but it’s a bit more manual than I had hoped.

Diff’ing wordpress releases

A new wordpress release is out and you’d like to know what’s changed? Sure, you can read the changelog, but is that REALLY enough?

Point your interweb box to: http://core.svn.wordpress.org/tags/ and then use svn to show you exactly what’s changed. Pick the URLs to the tags that represent the two releases you’d like to compare, and then:

svn diff http://core.svn.wordpress.org/tags/3.0.4/ \
http://core.svn.wordpress.org/tags/3.0.5/  > ~/tmp/wp-3.0.4_to_3.0.5.txt

Then inspect “~/tmp/wp-3.0.4_to_3.0.5.txt” to see what’s changed.

Nginx as a front-end proxy cache for WordPress

nginx-wp-love

The short version:

We put an nginx caching proxy server in front of our wordpress mu install and sped it up dramatically – in some cases a thousandfold. I’ve packaged up a plugin, along with installation instructions here – WordPress Nginx proxy cache integrator.

The long version:

Here at blogs.law.harvard.edu, our wordpress mu was having problems. We get a fair amount of traffic (650k+ visits/month), – combine that with ‘bots (good and bad) – and we were having serious problems. RSS feeds (we serve many from some pretty prominent blogs.) are expensive to create, files are gatewayed through PHP (on wpmu), and letting PHP dynamically create each page meant we were VERY close to maxing out our capacity – which we frequently did, bringing our blogs to a crawl.

WordPress – as lovely as it is – needs some kind of caching system in place once you start to see even moderate levels of traffic. There are many, many high quality and well-maintained options for caching – however, none of them really made me happy, or fit my definition of the “holy grail” of how a web app cache should work.

In my mind, caching should:

  • be high performance (digg and slashdot proof),
  • light-weight,
  • be structured to avoid invoking the heavy application frameworks it sits in front of. If you hit your app server (in this case, wordpress) – you’ve failed.
  • be as unobtrusive as possible: caching should be a completely separate layer that lives above your web apps,
  • have centralized and easily tweaked rules, and
  • be flexible enough to work for any type (or amount) of traffic.

So I decided to put a proxy in front of wordpress to static cache as much as possible. ALL non-authenticated traffic is served directly from the nginx file cache, taking some requests (such as RSS feed generation) from 6 pages/second to 7000+ pages/second. Oof. Nginx also handles logging and gzipping, leaving the heavier backend apaches to do what they do best: serve dynamic wordpress pages only when needed.

A frontend proxy also handles “lingering closes” – clients that fail to close a connection, or that take a long time to do so (say, for instance, because they’re on a slow connection). Taken to an extreme, lingering closes act as a “slow loris” attack, and without a frontend proxy your heavy apaches are left tied up. With a lightweight frontend proxy, you can handle more connections with less memory. Throw a cache in the mix and you can bypass the backend entirely, giving you absolutely SILLY scalability.

On nginx – it’s so efficient it’s scary. I’ve never seen it use more than 10 to 15 meg of RAM and a blip of CPU, even under our heaviest load. Our ganglia graphs don’t lie: we halved our memory requirements, doubled our outgoing network throughput and completely leveled out our load. We have had basically no problems since we set this up.

To make a long story short (too late), I packaged this up as a plugin along with detailed installation and configuration info. Check it out! Feedback appreciated: WordPress Nginx proxy cache integrator.