The other day I received a notification from my host that my site was requiring more CPU time than was allotted with the hosting plan. I’m allowed 10,000 CPU seconds within any given 24 hour period and 2,000 CPU seconds within any given 2 hour period.

Exceeding either results in a warning to start with, and presumably some form of lock down action if it were to continue without resolution. When I logged into cpanel to check my stats, er, Time to Loot was roughly double in each of those limits.

The only change I’d made recently was to the theme — I shifted from an Elementor driven setup to a Divi one. Specifically, a cut back version of the Extra theme (which has the Divi builder built into it). I worried that now that I’d customised Extra to my liking I might have to shift back if it was driving the extra script executions.

I kinda knew also that I’d been driving a fair number of scripts on the site (the most visible of which being the WP RSS Aggregator plugin which drives my blogroll). But nothing there had changed recently.

I was contemplating simply biting the bullet and upgrading to the next plan, but something about it all still seemed off. The daily traffic hadn’t even been that high. I mean it was good — but nothing out of the usual. So I struck up conversation with support and unlike how most stories that start this way go — I ended up with a good outcome.

Attaaaaack!

Yeah – so, turns out… Time to Loot was under threat from foreign hostile forces! It was under attack! :O

I was already running a WP Security plugin fortunately. Incidentally one that I thought might’ve been contributing toward the high CPU usage, but it had been in place for several months already. So they couldn’t really get to or do anything.

But here’s an interesting fact: WordPress has its own mechanism for launching scheduled tasks. It has built its own version of Cron in the form of the WP-Cron.php file. Every time this script is run, it scans your site for scheduled tasks that should have been done or kicked off at around the time of its execution.

But unlike a proper Cron job which executes fully from the server side — including the scheduling — wp-cron.php requires a different trigger to kick it off.

The folk at WordPress decided the best trigger was… Er… The loading of any other post, page or piece of content on your blog. Anything. Every time. Refresh a post 50 times, it will trigger wp-cron.php 50 times. Expand that out to 15,000 times and it starts to become a bit of a problem.

There was a bot crawling the site, pulling everything from it. It had consumed 2.2GB of data in a relatively short period and each page or post it hit triggered a check for other scripts to execute. I don’t even have 15,000 pieces of content here so who knows what it was doing.

In any case — like I alluded to; support was exceptional. They looked into the problem then and there over live chat and identified the problem pretty much immediately then gave me three fixes, the first of which they implemented on the spot on my behalf.

Solution 1: Strengthen the .htaccess file

While I had the WP Cerber Security plugin installed, preventing anything majorly bad from happening — this was still only preventing access after the request to server was already made.

The support agent I was talking to was able to implement the ‘6G Firewall‘ ruleset into my .htaccess file to prevent bad bots from even being able to get a valid response to a request against my domain.

It blocks a wide range of bad and unknown bot types, while not impacting search engine crawlers.

As long as your host is running Apache 2+ and has htaccess files enabled, you can drop this code in and with no further config enjoy much better security.

That alone probably would have solved the immediate issue, but this was just the first solution suggested.

Solution 2: Install ‘Wordfence Security’

It’s a plugin which at surface seems very similar in nature to the WP Cerber Security plugin I was already using.

But after installing and digging a little deeper, it does go at least a bit further it seems. The adjustments made to the .htaccess file are fairly static in nature. They’re wild carded to pickup a wide range of things but beyond that will be unchanging.

Wordfence even in its free version will dynamically learn from the traffic patterns hitting your site and can (with the right permissions granted) adjust your .htaccess on the fly to block new attacks.

Improving Efficiency

Solution 3: Reduce frequency of WordPress ‘Heartbeats’

So here’s something else I didn’t know WordPress did.

If you’re logged in to the Admin part of the site, e.g., the dashboard, editing a post, etc — WordPress updates your status every 15 seconds. This was identified as a potential tertiary problem in my case, as there had been a high number of admin-ajax.php executions as well. (Which in retrospect actually made sense, since I had a ‘new post’ page open for most of the day.)

The intent here seems to be mostly for multi-user blogs so that users can easy when other users are editing posts or pages. For a single user blog this could pretty much be turned off entirely to no ill effect.

I went with a bit of a compromise position though and set the heartbeat time to occur once every 60 seconds instead.

You can edit this into the WP config directly, but easier by far just to use a plugin.

Solution 4: Disabling WP-Cron and switching to ‘real’ Cron instead.

This one actually sits somewhere between security and efficiency, really. By disabling wp-cron.php; you remove this vector of attack against your server’s performance.

To disable WordPress from running wp-cron.php every time a page is loaded, you need to head into and edit your wp-config.php file in your main WordPress install folder. In there, scroll down until you find: ” /* That’s all, stop editing! Happy blogging. */

Right before that line, enter: define(‘DISABLE_WP_CRON’, true);

How you tell your server to actually execute the script will differ a bit from host to host. Fortunately on SiteGround (my host), their cpanel instance also includes a GUI for scheduling cron tasks.

But what you want to achieve is to essentially run the following command every 30 minutes:

wget -q -O – http://yourdomain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Doing it this way has a few other benefits too. e.g., Ever scheduled a post and had it completely fail to actually… You know… Post?

That’s because if you don’t have any visitors or site hits shortly after the time the post is scheduled to go — it just won’t. Running your wp-cron via ‘real cron’ on a reliable schedule essentially ensures this won’t happen any more.

Final Result…

…Back within the safe band of CPU seconds for both 2h and 24h measures again, so I don’t have to upgrade my plan. Thank God. I wasn’t looking forward to finding out what that price uplift would’ve been, but I would imagine it to be not insignificant.

In any case, huge thanks to the SiteGround support for being on top of this and helping me solve it. (Including giving a temporary reprieve on the limits while we were working through the issue.)

May not be the cheapest host provider out there, but this would be the third or forth time I’ve had to call on their support so far — and every time it has been superb. Can highly recommend if you’re in the market for a host.

If not, hopefully some of the other information in here might be useful to you!


Naithin

Gamer, reader, writer, husband and father of two boys. Former WoW and Gaming blogger, making a return to the fold to share my love of all things looty.

8 Comments

Nimgimli · October 30, 2019 at 2:15 am

I run Wordfence on all our sites and it has been a huge benefit. If this happens again, another free option is to put your site behind CloudFlare which can handle your SSL, serve as a CDN and acts as a firewall. It’s dead simple to block an IP, or even a country, from every getting to your server.

    Naithin · October 30, 2019 at 8:10 am

    Good to hear Wordfence has been working out well for you. I was a bit reluctant to switch over from WP Cerber Security at first. Theoretically, both can co-exist, but there is so much feature overlap and considering I was trying to *reduce* CPU usage… xD

    re: Cloudflare, I actually attempted this earlier on in the piece but then had routing issues as a result. I didn’t go into troubleshooting it at the time, so not sure what the issue was. Unsure if it was the Let’s Encrypt SSL Cert I had on the current server setup, or whether it was the permanent redirect I have setup in htaccess to ensure everyone lands on the https site or something else entirely…

    But still, good call. It is likely worthwhile to investigate a second go round and see if I can fix it all up.

Isey · October 30, 2019 at 2:18 am

I have no clue about any of this. I hope my friend who hosts me does! :)

    Naithin · October 30, 2019 at 8:14 am

    Hah, likely does if running a server!

    But from your side, the easiest thing to do yourself would be to install the Wordfence Security plugin and let that do its thing. You could also install the Heartbeat control plugin and change that, but if you haven’t had any issues with CPU usage then this is far less important as while it helps efficiency it isn’t a security issue at all.

Bhagpuss · October 30, 2019 at 4:24 am

This is why I’m on Blogger, which does everything for me. I would jack the whole blogging thing in rather than deal with any of that!

    Naithin · October 30, 2019 at 8:24 am

    Complete opposite for me — I’d rather deal with the occasional thing like this for the freedom otherwise to customise, get plugins, etc. I know you can customise to an extent (I actually briefly had a blogger blog waaaay back in the dark ages, lol)

    Still. WordPress self-hosted for all its problems suits me better. :)

Rakuno · October 30, 2019 at 8:05 am

Ah, thanks for all those tips!

I was having some trouble with my blog going offline from time to time and I was wondering what kind of shenanigans was going on. Unfortunately due to my social anxiety I kept procrastinating on contacting support and trying to solve the issue by myself to no avail… Well, it did stop on its own recently. *knocks on wood*

Still I will try to implement all the things you wrote here as I believe my problems were also related to bots.

    Naithin · October 30, 2019 at 8:26 am

    Good luck with it, Rakuno!

    Definitely the first two suggestions would be the most help if it is bot related. If you need any further help, hit me up in the Discord and will do what I can. :)

Comments are closed.