This is a story of implementing things I knew I should be doing, but didn’t QUITE realize the significance. Last year I did a talk at WordCamp Grand Rapids on caching. Things I talk about in this post will be based heavily on that.
I share a server with my friend Steve, and we sell shared hosting on it. It’s a VM from Agathon, and over the years we’ve boosted RAM and CPU as we’ve grown, but recently we had a very large spike in system resources, and started looking at other ways to tone it down a little.
A long term issue we’ve struggled with is attacks on wp-login.php. They hammer on it, on many of our sites at once, and it sucks up enormous amounts of resources. That makes our server slow, and thus our sites slow. We put some things in place to stop that on the sites that were getting attacked, but never made a concerted effort to enforce it on every site.
To be clear, Site A is being slow because Site B was being attacked. No amount of awesome on Site A is going to help it as long as Site B is killing it.
We also had WP Super Cache on some sites, but not all.
We also had nginx working as a reverse proxy, but the config was quite old, and we were really only serving CSS and some images with it.
With the above setup, starting last week we were regularly running out of 5G of RAM, AND 1G of swap. Additionally, load average was running at about 10 when quiet, 40 or 50 when busy. We have 3 cores on the CPU. As you can imagine this was completely unacceptable, and people were letting us know that.
We did four things to fix this.
- Install the plugin “Rename wp-login.php”. This is a very simple plugin that allows you to move your login to another location, whatever you’d like. I put this on every site on my server and then alerted the clients to the new security measures on their site. It works great, but the Error page it leaves behind still spins up PHP, which leads me to step 2.
- Have Apache return 403 on wp-login.php. This is pretty key, because Apache’s 403 page never spins up php, and uses FAR fewer resources. Here’s what goes in .htaccess:
#Rename wp-login.php via plugin by that same name <Files wp-login.php> deny from all </Files>
- Install WP Super Cache on ALL sites. In offering shared hosting I pretty much left it up to the site owners to install whatever plugins they wanted to make their site faster. If they want their site faster they’ll install a caching plugin, right? The problem with this is that Site A slowing down Site B issue. As a result I enforced installing WP Super Cache on sites on my server. I have WordPress accounts on all of them, and I simply installed it everywhere. It was in many places already, so I simply alerted my clients that I was installing a plugin to make their site faster.
- Make nginx serve static files properly. The sites are served by Apache, and we had nginx on there serving some files. We changed nginx to serve all static html files, which notably are created by WP Super Cache. nginx really shines most when serving static files, so this is a big deal. NOTE: this is the only part I didn’t do myself. I had Agathon do it.
After making these changes, our average load is less than 0.5, and we regularly have more than 1G free of RAM. That’s really a huge difference. We were considering moving to a new server, or splitting the sites in half and leaving half on the old server and all kinds of things. Now we’re solid until something changes (like more sites).