I’ve been dealing with a slow WordPress site for a while. In fact, it’s a whole series of slow WordPress sites. This site, along with a group of WordPress sites running in multi site, have never been quite as snappy as I’d like. And that’s weird considering that I’ve got another WordPress site running extremely well on the same sized droplet at Digital Ocean.
I’ve gone through all the normal fixes of optimizing the database, minifying JS and CSS, reviewing and changing memory settings for MySQL, and pretty much every other suggestion I could find online. They helped a bit, moving the server response time from 2 seconds to 1.9 or 1.5 on a good day. But it wasn’t significant.
A couple of days ago I took a look at and reviewed the access.log files for the server. And I was amazed at the number of times that wp-login.php was getting posted to. Guess that amazed probably isn’t the right word, but there were stretches where it was getting hit 5 or 10 times a second for nearly an hour. I’ve got the Limit Login Attempts plugin active on most of the sites so I’m not all that worried about them actually getting in. It was just the number of times that it was getting hit seemed to be a problem.
Even with Limit Logins, wp-login.php still needed to load WordPress each time that it’s hit. Loading the full WordPress stack 5 or 10 times a second so that a bot can try to break in is a waste of resources. A quick IP block and my server response time dropped to 0.6 seconds from around 2 seconds. Still not ideal, but way better. And it stayed that way until the bot started coming from another IP.
The next step was to protect the wp-admin.php file at a lower level before WordPress, or even PHP, gets involved.
First, you’ll need to create a password file. Through SSH you’d run something similar to the following. If you can’t get to SSH, your host probably has a tool in the control panel to do this.
$ htpasswd -c /home/username/.wpadmin username
It’ll prompt you twice for a password to make sure you’re entering the same thing.
And then you’ll need to add the following to your site config file, although you can probably do the same through .htaccess. I typically don’t use .htaccess, so I’m not sure if the syntax is exactly the same. I put this in /etc/apache2/sites-available/site.com.conf
<FilesMatch "wp-login.php"> AuthName "Login" AuthType Basic AuthUserFile /home/username/.wpadmin require valid-user </FilesMatch>
A quick restart and now any request for wp-login.php will bring up a login prompt.
Did it work
I tried just about everything I could find online on how to fix a slow WordPress site. And really, most everything I tried worked to make it a little better. But this appears to be the single change that’s made the most significant difference.
Looking through the log files after this change the hits on wp-login.php are still there. But now a log file review is showing a 401 response code instead of a 200 which means that Apache is blocking the request before it even gets to PHP and WordPress.
It’s still probably better to block the big offenders through something like iptables so that they’re stopped as soon as the packet comes in and keep even Apache out of it. But at least this saves PHP and MySQL from having to do anything. –Ryan