I am Kraft — Kraft.im

BrandonKraft.com ran on WP Engine. It had been for years now after being given a lifetime free developer account by a small little hosting upstart in Austin.

All in all, I haven’t had any problems with them. I noticed changes as the mainstays of the company that I knew—Trafton and Austin, for example—left to do other things, the rebranding away from “engine” fast car idea to the current one. Support has changed, slipped perhaps, but I’m not a normal character and my requests aren’t typical, so I’m willing to forgive.

In any event, time for something new. The big push was SSL. A friend had a cert available he wasn’t going to use, so I was going to give SSL a spin. At the time, WP Engine didn’t allow SSL on the comped plan, so the wheels started in motion. The engine started…

The Setup: WordPress

I run a lot of WordPress personal/family sites, random idea sites that never took off, and, well, more WordPress sites than I care to admit. I’m a little tired of managing 30+ WP installs, even with a tool like InfiniteWP.

Multisite was always an option, but domain mapping felt clunky. A light bulb erupted when I watched JJJ’s WordCamp Chicago presentation on multinetwork multisite WordPress installs. (h/t George).

If you’re into WordPress and haven’t heard of this, watch this video.

tl;dr: WordPress has the internals to not only handle multiple blogs under one site (to use the one set of internal lingo) or multiple sites within one network (to use the other set of internal lingo) which is commonly known as multisite, which is one network at example.com spinning up sites at *.example.com or example.com/*, but to handle multiple sites each with multiple blogs (or multiple networks each with multiple sites) on a single install!

Now, yes. The above sentence is very confusing. WordPress refers to a single “web presence” as both a “blog” and a “site” in different places and a collection of “web presences” based on one site as both a “site” and a “network” in different places. The code with examples like the function is_user_member_of_blog or the variable $blog_id refers to a single web presence as a “blog” while talking about it as a “site”. Multisite is really multiblog, per the nomenclature used in the code. $site_id refers to the top-level network, hence using the “Network Admin” to add sites, which are really blogs, to the instance. Multinetwork is actually multiple sites. What? Right. I mean, it makes sense eventually once you suspend most logic.

Anyhow. I’ve probably driven away 85% of my traffic by this point, so let’s keep going with you dedicated few.

In short, everything that I’m okay being in the same database—family, personal, and silly one-off sites seem ripe for this—can be moved into “The Instance”, borrowing from an old term I’ve heard used describing the setup of w.org.

What About The Box?

Next, the infrastructure is important. A regular host wasn’t going to cut it for me. I’ve done shared hosting (both done poorly and done well) and I’ve done managed WordPress hosting. I opted to go with Linode spinning up a box using Nginx and php-fpm.

To make things secure for visitors, I installed the SSL cert. Nginx makes it stupid simple to setup SPDY—Google’s future implementation of what will evhopeally get rolled into HTTP2 to make super fast transfers over HTTPS. Seriously. Change listen 443 ssl to listen 443 ssl spdy.

I wanted my HTTPS implementation to sing though. Really sing. I updated the ciphers accepted to the current suggested best set, which did knock out IE8 on XP support, but oh well. I also activated HSTS—Strict Transport Security–which instructions browsers to force HTTPS and not to allow the user to bypass a problem.

Caching

Initially, I had WP Super Cache running to cache the site until I could get some action with a more powerful native caching solution. I love WP Super Cache. Sure, it is a little long in the tooth and could use some love. I’ve joined Donncha in maintaining it, but do hope to do more than maintain in the future.

For this project, though, I opted for Redis for object, page, and user session caching. Zoom zoom!

An example: My wife’s site, Living La Lupe, was taking 1.6sec to load on WP Engine. Enabling HTTPS SPDY and moving it to my new server: 622ms. (Note: The transfer process borked the sidebars for her site, so I had to recreate them, so there was a slight difference between the two tests.)

Zoom zoom!

Lessons Learned

There were plenty of outages for the site during the transition. Nginx rules aren’t Apache .htaccess rules, so there was plenty of learning to be done. The worst outage was after restarting the computer, the modifications I had made to the firewall hadn’t stuck. The difference of settings told the server to reject all traffic from ports 80 and 443—the ports for regular HTTP and HTTPS traffic.

Additionally, HSTS is serious. I added the includeSubDomain option which does exactly what it says it will do—force HSTS on subdomains. I didn’t think through that I had two production sites on subdomains still on my old server and/or WordPress.com that didn’t have a HTTPS option in place. Don’t enable that until you’re ready :).

Pulling the Plug

That’s enough technobabble for now. If you’re curious about how I set up any piece of the site, drop a note in the comments. The process wasn’t as painful as I expected and, as always, there are plenty of folks online willing to help. Erick Hitter helped a great deal with both code, suggestions on Nginx rules, and allowing me to gripe here and there when I had no idea what was going on.

And there’s your incomplete, 1000-word guide on setting up your own over-engineered website.

Update: I’ve added HHVM with a PHP-FPM fallback.