Proxy caching WordPress with Nginx

Nginx is a lightweight web server/load balancer/reverse proxy designed to drive blazingly fast websites. It has low resource requirements compared to Apache, the defacto standard for PHP-based applications, and can handle an order of magnitude more requests per second.

With WordPress, Nginx is often used in a few different ways: to serve static media assets, to execute PHP for WordPress, or to reverse cache Apache responses. You’ll want to install Nginx, put it in front of Apache, and then choose one option or go for all three. Mike Green has comprehensive documentation to cover the first and third scenarios. It’s more or less what I did at the J-School.

Epic foo is using Nginx as a reverse proxy cache. “Reverse proxy cache” means Nginx will generate a static cache of everything Apache responds with, and then serve this cache as long as you’d like. For us, this means homepage response time has dropped from an average of 1.5 seconds to around 25 milliseconds. On pages without a lot of secondary images and Javascript (e.g. not the homepage), load times are now wicked fast.

It’s worthwhile to note we’re only serving cache to non-authenticated users. Students and faculty expect our website to behave like an application, and to have changes they make appear immediately. This is less of an issue for other visitors. Caching also gives us protection against bursts of unexpected traffic.

Proxy caching was deceptively simple to implement. I spent around 15 work hours in September trying to get it to work, gave up until November, and then solved the problem in 15 minutes with a stroke of brilliance. Originally, I followed the configuration settings specified in Dan Collis-Puro’s awesome WordPress plugin and it took our setup to 80% completion. I then learned the most important thing is to tell Nginx to log cache hits; this makes it far easier to determine whether caching is working or not. The second most important thing is to turn proxy_redirect off. I still don’t fully understand what the declaration does, but it was the crucial missing piece. Seeing dozens of “HIT”s scroll by never felt so good.

Check out our commented master Nginx configuration file [txt] and the configuration file specific to [txt].

Easiest way to add Git to your WebFaction account

tar -xvf git-
cd git-
./configure --prefix=$HOME
make install

If you’re reading this in the future, you may want to use the most recent version of Git. Instructions via the always helpful WebFaction support team

How to properly use Git with Subversion

Find this post on the Google or someone’s shared link? I’ve discovered an even more magical way to work with Git and Subversion

Having Git properly interface with Subversion is a mysterious black art. If you’re into the Harry Potter stuff, then this post is for you.

First, I must give credit where credit is due. Boone Gorges has a nice writeup detailing how he uses GitHub with Subversion. Unfortunately, it only tempted me. What really set me on the right track was a short piece by Evgeni Golov, which had everything but one crucial piece: checkout instead of merge.

Using checkout instead of merge is likely the most critical piece to this puzzle. What Erik and I found the first time when using merge is that Git treats both versions of the code as equal and tries to find the middle ground between them. Instead, we want to update all of the files in the Subversion repository with their most recent counterparts from GitHub. Checkout gives us exactly this power.

Because I was working on this Monday night with the Assignment Desk, I’ll go step by step with those links as an example. This tutorial assumes you’re doing all of your development with Git, and need to occasionally push to Subversion with releases.

First, clone your Subversion into your local Git repository:

git svn clone -s -r274218

Notice two important flags: -s and -r. The ‘s’ flag tells Git the code you’re importing follows the normal Subversion folder structure, or /trunk/, /tags/, and /branches/. The ‘r’ flag tells Git to import after the specified revision number; when pulling from a large Subversion repository like, this can save you days of time. You can find the ID for your first commit in your revision log (Assignment Desk example).

Change into your newly-created directory and pull in your Subversion history (could take a bit of time):

git svn fetch

Once all commits have downloaded, add your working GitHub repository as a branch to your local Git repository:

git remote add -f github

What’s next is the magic part. We’re going to checkout the code from the ‘github’ branch to the ‘master’ branch (our Subversion checkout), instead of merging the two:

git checkout github/master *

If you use ‘git status‘ at this stage, you’ll notice all of the files you’ve changed since your last release have nice little M’s next to them. If you had merged, there would be a nasty mess of conflicts you’d have to resolve.

Add all of the files you want to save in the next commit:

git add *

And make your commit:

git commit -m "Updated from GitHub"

Aside: at this point, I tried to push back to and received an error of “Merge conflict during commit: File or directory ‘assignment_desk.php’ is out of date; try updating: resource out of date; try updating at /usr/local/git/libexec/git-core/git-svn line 572,” also known as nonsensical gibberish. Thankfully, the Google pointed me to this Stack Overflow thread.

Before you celebrate, you must practice one last piece of magical foo: rebasing. For reasons we don’t fully understand, rebase holds the key to resyncing your Git commit history with Subversion. Make it happen:

git svn rebase

Push all of your changes back to the original repository:

git svn dcommit

Congratulations! You’ve tamed the beast and progress to the next level.

Using Google Apps with StatusNet for email notifications

For the sake of saving an hour of guessing, here are the proper settings for using Google Apps, or Gmail, with StatusNet, formally known as Laconica:

$config['mail']['backend'] = 'smtp';
$config['mail']['params'] = array(
'host' => '',
'port' => 587,
'auth' => true,
'username' => '',
'password' => 'your_secret_password'

Adding these settings to your config.php file will allow your StatusNet instance to send email notifications over SMTP when your web host doesn’t support sending mail from the server (ahem, WebFaction). The trick is to use the proper port, 587 instead of 25, and to enable authentication.

I’m still trying to configure Google Apps as the XMPP provider for StatusNet too; I’ll put together another post if I can figure that out.

#wcpdx: Speed Up WordPress

First session at WordCamp Portland this morning was “Speed Up WordPress” with Jason Grigs of Cloud Four. He jokingly argues that “we’ve remade the internet in our image and the image is obese.” Since 2003, web page size has tripled, number of objects has doubled, and we can partially blame it on WordPress. On the developer’s side, the expectation is that everyone is going to be on a fast connection, with broadband at home or at work.

Page load time, however, determines whether people will stay on your site and do what you want them to do. Speed and performance affect can change perceived quality and credibility of the website. “You can have a great brand and your site is really slow and people will think you’re crap online.” It’s critically important that your application maintains the user’s flow and focus. Amazon says they lose $1 million for every extra second in their shopping cart experience. There’s also an environmental impact for slow site. The number of data centers in the last four years has doubled, and has an energy consumption equivalent to five 1,000 megawatt power plants or the entire state of Mississippi.

In short, build a site that is optimized and doesn’t use more resources than it needs to. Be proactive about it.

Continue reading #wcpdx: Speed Up WordPress