Posted by & filed under Blogs, Computers & Internet.

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.

Protecting wp-admin.php

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/

<FilesMatch "wp-login.php">
	AuthName "Login"
	AuthType Basic
	AuthUserFile /home/username/.wpadmin
	require valid-user

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

Posted by & filed under Computers & Internet.

For another site I needed a way to automatically post to a Pinterest board. It’s a WordPress site, but I didn’t want the posting to be based on when a post went live. I needed a way to automatically post whatever the newest post was that hasn’t already been posted. I’ve already done something similar with Facebook, Twitter, and Tumblr; but since there isn’t a public API for Pinterest yet it wasn’t quite as easy.

What I found was a node.js library called pin-it-node that lets you post to Pinterest. Once that was loaded it was a pretty easy jump to write the following little script to take a couple of command line options and post to Pinterest.

So, I added an action to WP cron that fires every day around the same time that finds a post and then calls this script with the right command line options. At least for now, it’s working without a hitch.

If you’re running from the command line, it’ll look something like this.

$ node pin-it.js "Pin Title" "This is a description for the pin" "http://example/image.jpg"

If you’re interested, the board that’s getting filled is here. Each day there are two fonts – one recent and one random – pulled from and added to the board. And I also put up a quick page to figure out the numeric board ID which you’ll need for this.

Posted by & filed under Moodle.

I’ve been using my unittest Moodle question type pretty much since the beginning of this school year. But a couple of things have been bothering me as I watch students work on code problems.

The first is that their only feedback for a failed JUnit test was the stacktrace that JUnit kicks out. For students new to programming, that is both intimidating and almost totally worthless. So, I went in and parsed out the failure messages and now they’re displayed in a table with just the message about what was expected and what was returned.


Next, the plugin that I used as a starting point had a field on the question editing page where you entered the name of the JUnit test class. But you didn’t have to do that for the student class file because the student’s file would be parsed to pull out the class name. Went in and did the same thing for the JUnit test classname and removed the field.

And last was something really trivial, but one that bothered me more than it should. When the ace editor loaded it was scaled to the height and width of the textarea it was replacing. Worked great, until the student resized their browser. So a bit of CSS and the editor window is always 100% of its container.

Pushed an update to GitHub a few minutes ago and uploaded it to my Moodle server. Haven’t had a chance to test it live with students yet since it’s Saturday, but we’ll give it a kicking on Monday and see how it goes.

Posted by & filed under Moodle.

moodleiconOver the summer I took a Moodle unit testing plugin and updated it so that it’ll use JUnit 4 and improved on the interface a bit. Since the school year started I’ve been using it with my students, and up until a couple of days ago it worked without a hitch.

What caught us is that we were giving a test to about 55 students at the same time, and they were all submitting Java code to my little $10 a month DigitalOcean VPS droplet. About 30 minutes in everything slowed down to a crawl. Server load was about 60x over max and there were around 250 instances of javac running.

Fortunately, it was a pretty easy fix. I had my students sit back, take a deep breath, and not submit anything for a couple of minutes. That took care of 27 of the 55 testers, and it was enough to get the server load down below 10. Still high, but you couldn’t tell by the speed of the server. It was reacting just like it should.

Most impressive is that the server never actually crashed. The droplet only has 1gb RAM along with a 2gb swap, but while I was watching it never had to touch the swap.

Guess the lesson is that we probably shouldn’t test 55 students at the same time if they’re all going to be writing and submitting code.

Posted by & filed under Coding.

OctocatLearned an important lesson today.

I spent a good chunk of yesterday working on a new project. It’s a Moodle plugin that, when finished, will let you put code online for your students to work on along with tests so they know when they’re done and you can automatically get back a grade.

But while deactivating the plugin in Moodle so that I could reactivate and trigger database table creation I accidentally clicked the button to delete the folder from the computer and everything I did yesterday disappeared.

First step when I started over this morning was to commit it to GitHub and then committed fairly regularly today so that I didn’t lose to much if I do something stupid again.

Posted by & filed under Computers & Internet.

Logged in this morning to a small VPS that I have hosted at DigitalOcean and saw a notice that Ubuntu 14.04 was available, and that I should upgrade from 12.04 that was currently on the box. Did a bit of research, and figured I’d go ahead and do the upgrade. Nothing really critical was on the server, so it didn’t seem all that important, but I didn’t like the idea of having an outdated version of Ubuntu on my VPS.

So, I did exactly what was suggested…


Appeared to be working okay, until about half way through and errors started popping up that files couldn’t be found – 404 status codes.

The VPS restarted and that’s when the real fun began. Got an error that the file system was read only and to go to a recovery console, which I did. An fsck determined that the file system was okay.

What I decided to do, after much Googling, was to try the upgrade again from the recovery console.But I had to overcome a few snags.

First step was to remount / in read / write mode. In recovery it was read only.

mount -o remount,rw /dev/vda /

/dev/vda might also be /dev/vda1 depending on how you setup the droplet originally. This gave me access to where I could write to files.

Next I needed networking. Originally I went and manually setup eth0 to the settings for my droplet which are, very conveniently, shown under the VNC window in the DigitalOcean control panel. Turns out, there was an easier way.

service networking restart

This loaded eth0, which I had already done, but also lo and eth1. Didn’t need those two, but it was also a shorter command.

This didn’t bring up DNS though. I could ping remote IP addresses, but not look up domain names. The DNS servers were correctly set, just not working.

So what I wound up doing was to set the two domain names I needed, and, in the /etc/hosts file so they didn’t need DNS with the following two lines.

You’ll probably want to review that those two IPs are still correct, and also change from nyc2 to whatever data center you’re in.

Then, ran the upgrade command again and after about 30 minutes of watching the console scroll by version 14.04 was up and ready.


Only snag I’ve found so far is that Apache is giving me a forbidden error which is probably just some permissions deal coming from a newer version of Apache in 14.04 compared to 12.04. But, SSH is working again so I can now go through PuTTY instead of the VNC console and get everything back where it needs to be.

Posted by & filed under Moodle.

I’ve been playing around with Moodle plugins for the past few days and have kicked out a couple that are working, at least well enough for me to use.

One of them solved a pretty trivial task for me, but one that should save some time down the road. And that’s formatting.

Teaching Computer Science I type a lot of code into question banks. Sure, the WYSIWYG editor in Moodle makes it pretty easy to change fonts. But I wanted something more like BBCode that’s popular on web forums or shortcodes in WordPress. Something that lets me keep my hands on the keyboard and not having to mouse around to change fonts.

What I came up with is a filter plugin that I’m calling Easy Filter. From the admin settings pages you can define a tag to wrap around question text and then what the filter puts in place before and after that text as the page is displayed. For example, I have a ‘java’ tag setup that I’m using to wrap around any Java code in questions or pages. When I wrap Java code like this – [pre]System.out.println(“Hello”);[/pre] it  wraps it in a <pre> tag to format in a monospaced font.

And, here’s a screenshot…


The screenshot has 3 different tags defined, along with their before and after HTML. The bottom form is for adding more tags. To remove a tag you just blank it out on the list and hit the Update button.


The plugin is hosted at GitHub. Once you download the zip, you’ll need to upload everything to the /filter/easyfilter/ folder under your Moodle root.

Posted by & filed under Moodle, teaching.

Bob was absent yesterday and has to make up the test. Jane didn’t do so well and you want to let her have a second attempt. You’re only giving students 10 minutes for the quiz today, but Chris just needs a few extra minutes.

What you need is a user override. Not sure when this was added to Moodle, but I found it while setting up my Moodle 2.7 server for next year; and it looks like something that will get a lot of use.

The basics are that you can give a user, or a group, slightly different restrictions on a Moodle quiz. Read more »

Posted by & filed under Coding.

Not sure this is the best way to do this, but it works.

Working on a project and I’m writing a lot of code to do RegEx searches. Each match is 3 or 4 lines to do the match, check if there was a match, and then do something with the match. Since I was tired of typing the same code over and over, kicked out a little function to do it for me.

It also was an excuse to try out Gists and embedding them back on my site instead of putting the code directly in a post.