About this site

On 18 May 2016 I decided to refresh my primary blog, which up until this point had been hosted at wogan.me, using a custom domain pointed at wordpress.com

There are posts from all the way back in 2011, which is more than a little crazy to me.

In any case, I didn’t want to ditch any of it, so the entire history is archived here. All comments are disabled.

You can follow my real blog (and get ahold of me) at woganmay.com

Get system information in Laravel 5.1

I’m developing a software agent (using Laravel 5.1, because why not) that’s meant to run on an “IoT” device. I put “IoT” in quotes, because anything that has an Intel i3 and 128GB SSD, despite being Internet-connected, doesn’t really qualify as an IoT device to me.

One of the things this node needs to be able to do is send back information about the system (load, RAM, HDD, and so on). After a little bit of digging I found a library (jrgp/linfo) that does most of the heavy lifting right upfront.

In composer.json for your Laravel project:

"linfo/linfo": "3.0.0"

Now run composer update. You could use an alias for it, but I didn’t bother for my project, instead using the sample code provided by the vendor:

$linfo = new LinfoLinfo;
$parser = $linfo->getParser();

That $parser object can now return a whole bunch of information as PHP objects. Check this gist for a sample of all the information available in v3.0.0 of Linfo. Some are commented out because I couldn’t get them to work right upfront.

Today, I stared into the eyes of God – and saw only emptiness

There’s a chance, a very small chance, that I’ve got this wrong, and that I actually dealt with a human being. There’s a much bigger chance, though, that I dealt with a prototype AI. In either case, the service was absolutely terrible.

So, some background. I have paid-for Google Drive storage. For some weird account-related reason, Google has failed to invoice me for it for the last 3 months, so Gmail now thinks that I’m out of storage and will soon be unable to send emails.

Naturally, I contact support, using the Chat option, because I prefer IM. I explain my problem, and the support rep tells me they’re escalating it, and to expect a response within 24-48 hours. Fair enough, it’s a complex billing query that will take some senior involvement, I’m fine with that.

Few hours later, I’m browsing the web when I come across an interesting project – IPSoft’s Amelia. It’s an AI that can apparently teach itself based on the interactions of colleagues, stored knowledge on intranets (and the internet) and is apparently able to read the emotional state of the end user and react accordingly.

The video talks Amelia up like it’s about the end the tyrannical reign of human-staffed call centers TOMORROW. But then that’s marketing, and marketing is usually BS.

That’s when I spotted this:

2016-01-18 22_00_21-Settings.png

Now that sounds suspiciously like the exact encounter I had with the Google support rep earlier. Is there a chance that one of the “multinationals” testing Amelia, that IPSoft coyly refuses to name, might be Google?

Ok, so, simple test. I figure: I’m gonna contact support with a fake issue. It will seem real, and I will provide the answer in the original question. Any human would be able to iron it out in a few minutes.

So I go to the support page, select the Chat option, and populate it thus:

2016-01-18 22_01_32-Contact us - Drive Help.png

I include my email address there to prove that I’m authenticated into this session, and would hope that this authentication would be leveraged to provide some basic insight into my account standing to the agent I’m about to speak to.

Assuming I reach a real human being:

  1. They’ll immediately spot my bogus support query (if they’re smart), or
  2. They will respond to the built-in instruction (if they’re not) and ask me to close PowerPoint, or
  3. They’ll possess sufficient initiative to look up my account status and find I’m using 19gb/15gb available storage, and so will not be able to upload more files until I purchase more storage.

I hit Submit, and a few seconds later I’m connected with “King R”. And so begins my quest to resolve my support issue.

2016-01-18 22_24_57-2016-01-18 21_32_33-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

I should stress that, as I begin this journey, I’m only about 20% confident that I’m dealing with a bot of some sort. Watch how quickly that deteriorates into absolute certainty.

2016-01-18 22_25_29-2016-01-18 21_32_33-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

I provided the (bogus) error message right upfront. It’s a common error message in programs that require a file lock in order to read. Chrome requires no such lock – it can read files even though other programs are accessing them.

A human engineer would know this. Or, if they didn’t know, would react immediately to the obvious solution hidden in the question: Close the offending program. That did not happen.

2016-01-18 22_25_59-2016-01-18 21_34_17-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Again: Google Drive supports drag-and-drop, has done for years. They should know I’m using a modern, Javascript-capable browser by mere virtue of the fact I’m using a Google Talk widget to interact.

However: I asked a clarification question, when I couldn’t find the Upload button. Humans do this all the time – we say short things when we mean longer things. In context, I’m trying to upload a file, so obviously I need the File Upload button. The agent (or bot, 40% confidence) doesn’t understand that.

2016-01-18 22_27_08-2016-01-18 21_36_16-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

That detour seemed unnecessary, since I was able to successfully follow prior instructions. At this point I’d start getting irritated with this agent, but we forge ahead.

2016-01-18 22_29_20-2016-01-18 21_40_16-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

We have now managed to manually upload the file – or, not. Now, note the several cues in this exchange so far:

  • Based on my first response, PowerPoint is still open. I haven’t been asked to close it yet, which would theoretically resolve the issue “the file is open in another program”
  • The error I get is a generic upload error, for a file type that Drive is known to support. The issue cannot be the file.
  • If it worked earlier, but it doesn’t work now, and I’m trying the same process (which by inference I am), then the state of SOMETHING has changed between then and now. Which flies over King’s head completely.
  • Finally – I’m getting irritated, using words like “I don’t understand” and “it worked” – any human would read that as Annoyance. Not our brave King though!

2016-01-18 22_32_02-2016-01-18 21_40_16-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png


Note that I helpfully told it that I got an error, provided the error in quotes, and told it that I got “the same error as before”. As a human, you understand that to mean”the last error message I shared”.


2016-01-18 22_32_59-2016-01-18 21_42_18-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Irritation levels = rising. King either can’t keep up, or is reading from a badly-malformed script.

But, we forge ahead.

2016-01-18 22_33_44-2016-01-18 21_42_54-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

At this point, huge ass red flag: maildrivetest.

If I were setting up mailboxes to test a new support system for Drive, I’d call it pretty much that. Very, very good chance we’re dealing with a bot here.

Also note, it asks me for a screenshot. Now, in this scenario I’m obviously playing the dolt. Nowhere in the help interface does the means exist for me to take a screenshot. I might be smart enough to push the Print Screen key, but what do I do from there?

2016-01-18 22_35_19-2016-01-18 21_43_05-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

No instructions, even when I explicitly ask for it. Had it simply tried Googling for “How to take a screenshot” + “on Windows” (the platform being broadcast in my user agent) it would have resulted in:

2016-01-18 22_08_15-Settings.png

That could literally have been provided point-by-point. Of course, King doesn’t give me a chance to take the screenshot, and seems to forget about the screenshot immediately when I tell it that I have no idea how to take the screenshot.

At this point, I get the message “Please give me one moment”, which I think is a smokescreen to quietly connect my session with another agent, either real or virtual. That would be the most seamless way to dial in a real human being and solve this thing once and for all.

But no, it gets funnier.

2016-01-18 22_36_33-2016-01-18 21_45_52-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

King’s sibling (let’s call it “Rook”) correctly asks me to close the offending program. However, it misses the huge contextual question that is, “In PowerPoint?”. The answer is obviously Yes – we haven’t dealt with any other programs or files so far.

However, Rook is a bit smarter – it guides me, as a human would, towards the X:

2016-01-18 22_38_08-2016-01-18 21_45_52-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

So far so good! Also note the typo, “uploa dit” – that’s the sort of thing a human might do. Bots are capable of responding in annoyingly perfect written English, so the best way to obscure that is to introduce the odd spacing error.

Don’t worry, though – Rook suffers from the same intractable disease as King: Absolute failure to read the human condition. Which we’ll expose in due course.

2016-01-18 22_40_00-2016-01-18 21_47_35-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

I get the same error as before, helpfully provided in quotes. It then asks me for the error message, and for any numbers – obviously, you’ll get a more confident search result with an exact error code. This would be the first thing I’d ask for, since those cryptic codes usually yield exact results.

And now, ladies and gentlemen, the Caravan of the Mystical takes a hard left:

2016-01-18 22_41_06-2016-01-18 21_47_35-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Why on earth is the Drive App suddenly a factor? If I were an inexperienced and irritable human, I might take offense at being asked to install additional software all of a sudden. So I do just that.

2016-01-18 22_41_33-2016-01-18 21_48_21-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Observe the first-class EQ module of this bot fail to recognize that I’m getting irritated. That’s the first exclamation mark I’ve used all session, should be a hint, right? Instead it asks me what browser I’m using – a curious question since it can just read my User Agent and find out I’m using Chrome, but OK:

2016-01-18 22_41_59-2016-01-18 21_49_11-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Now it suggests Incognito?

For the uninitiated: Incognito is a safe mode in Chrome that lets you browse anonymously. It forgets everything – your history is wiped when you close the browser, and it doesn’t bring over any information from your regular Chrome browser when it runs. Information like, being logged into Drive.

Any Google employee, whether on-site or remote-outsourced, would likely have gone through basic training on how to use Chrome, and some of the essentials. Someone in Support would have definitely had training in how to use the basic features of Chrome, of which Incognito is one.

Said agent would immediately recognize that switching to Incognito would solve nothing. I’m using the same browser, with the same file, and am still facing the same issue uploading to the same account, which is still over-quota, an issue that neither King nor Rook have considered yet.

I know for a fact that Incognito won’t solve my problem, so I don’t bother trying it. Instead I wait a few seconds and:

2016-01-18 22_45_01-2016-01-18 21_49_11-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

And now, ladies and gentlemen, the moment at which the true nature of this digital beast is exposed and understood. Marvel at the deft and utter mishandling of one of the most common scenarios among technologically-challenged users.

I’ll be here all week.

2016-01-18 22_46_03-2016-01-18 21_51_12-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

I’ll give you a moment.


Ok, here are the critical mistakes that Rook has made so far:

  • Asked me to try Incognito in the first place
  • Does not understand that a password is required to authenticate
  • Does not understand that I do not have the password
  • Does not understand that the issue cannot be browser-related at this point, given that Google built both Drive and Chrome, that Javascript is working just fine, and that two upload methods have failed.
  • Does not understand that I simply could have asked my wife

At this point, as both the fictional high-maintenance user I’m roleplaying, and the actual technically-savvy user frustrated at the pace of AI development, I pitch it a wide.

2016-01-18 22_48_33-2016-01-18 21_51_12-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Note how I did two things in that sentence:

  • Ended the conversation – “don’t have time”
  • Solved my own problem – “Dropbox instead”


This is case closed. This is when any human support tech would apologize that they were unable to solve the issue, and wish me a good day. Then they’d close the window, exhale, and remind themselves that it’s only a few days left until Friday.

But Rook?

Rook don’t give a fuck.

2016-01-18 22_49_53-2016-01-18 21_51_12-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

So at this point, you might share in my frustration on many levels:

  • It’s not my job to troubleshoot your software
  • I’m clearly annoyed at you, and have my own alternative
  • I do not wish to continue this conversation

Which Rook picks up on about half a second later, without giving me a chance to respond:

2016-01-18 22_51_28-2016-01-18 21_51_29-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

Wow. So it did two things at once:

  1. Read that I was upset and tried to calm me down (good)
  2. Also read that I said I don’t have time anymore and wanted to end the conversation

We’re 110% into badly-written deep-learning bot territory at this point. I’ve got what I came for – no human agent I’ve ever met would handle such a simple support request so badly. So I decide to leave an ambiguous message for the developers of whoever put this AI together.

2016-01-18 22_52_44-2016-01-18 21_51_29-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

That of course is not a reference to Drive. At this point I’m hoping that a human is either watching, or will later review this log and realize that I’m referring to the bot AI, not Drive.

Note, again, that I’m giving Rook an out: I’m giving it the keywords “not getting the help I need”, which is generally what humans say when they need their request escalated.

But there are no supervisors. There are no escalation paths.

There is only Rook.

2016-01-18 22_53_42-2016-01-18 21_51_52-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png



2016-01-18 22_54_31-2016-01-18 21_53_38-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

The single most offensively-human line I’ve heard in this entire exchange yet.

I know it doesn’t know the answer at this point. Rook knows that I don’t know the answer. At this point, even the most basic SQL query would know to take it upstairs.

But this is Rook. And Rook does not surrender.

2016-01-18 22_55_38-2016-01-18 21_53_38-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

And as I feel the hopes and dreams of a thousand Ray Kurzweils melt away in the sheer furnace of Rook’s stubborn inability to solve a question that anyone, possibly even a man off the street could solve, I call it a night.

2016-01-18 22_57_03-2016-01-18 21_53_38-(3) Google Support, King R, Wogan May.png - paint.net 4.0.6.png

I do not wait for Rook’s response.

Finally, a better News24

On 11 September 2015 we’ll all be witness to a seismic change in online discourse here in South Africa. The largest online news hub, News24, will be disabling their comments section.

Personally I think it’s a fantastic move. Comments, especially on controversial articles (of which there seem to be many) can easily get out of hand. The readership on News24 seems mainly to consist of paranoid, angry people who have little else to do than bemoan the state of affairs in South Africa, often tending towards racist slurs and religious intolerance.

Or just plain-old brickheadedness. Take a look at the highest-voted comments on the above opinion piece explaining why comments will be disabled:

The cutting edge of online discourse in South Africa. Emphasis on "cutting".
The cutting edge of online discourse in South Africa. Emphasis on “cutting”.

There’s a couple of huge ironies in those comments, for one: That disabling comments curbs free speech, despite the fact that Facebook, Twitter, and every social network we know of is not banned (or even monitored) by our government.

The other irony – News24 offers regular users the ability to upload articles and publish them on News24.com, subject to a limited editorial process. And they put this right on the home page, making no attempt to hide it:

And I've uploaded two of the things myself.
And I’ve uploaded two of the things myself.

And when I say “limited editorial process”, here’s a quick sample of the sort of stuff they allow people to publish:

  • http://www.news24.com/MyNews24/Ok-lets-assume-you-are-perfect-20150907
  • http://www.news24.com/MyNews24/How-to-ruin-the-day-20150907
  • http://www.news24.com/MyNews24/Zumas-Nkandla-Contribution-to-Load-Shedding-20150210
  • http://www.news24.com/MyNews24/I-luuuuuv-my-gun-20150903
  • http://www.news24.com/MyNews24/The-Real-Housewives-of-Nkandla-Episode-5-20140331

Some well-written, some poorly-written. Some critical of our president, some not. A good couple of completely incoherent rants. All of them expressions of free speech hosted at News24’s cost.

The biggest irony, though, are all the people vowing to never come back to News24. I’d hazard a guess that they’re the sort of people that didn’t bother actually reading the articles. They came to the site to spar, to fight, to punch eachother up in the comments section, not to actually read any of the content – and then, straightfacedly, accuse the site of having poorly-written news.

It takes fractionally more effort to submit an article. Instead of being able to click right into a comment box and crap all over the page provide feedback, you need to click this little button first:

2015-09-08 09_16_47-The Real Housewives of Nkandla _ Episode 5 _ News24

That’s literally all there is to it. The next step is to dump your insecurity, racism and paranoia into a slightly bigger textbox, and once it’s submitted, it’ll vent all over News24’s readership within a few hours.

But that little Upload button seems to make all the difference, representing an insurmountable obstacle to the fine champions of online discourse that currently inhabit the News24 comment section. To them, putting the comment box in a modal popup is tantamount to censorship, a fundamental assault on our right to say whatever the fuck we want, to whoever we want, taking no responsibility for the consequences free speech.

And that’s probably the biggest gap in their reasoning. Anyone, with a few minutes of effort, can get themselves set up on wordpress.com, or blogger.com, or iblog.co.za, or a hundred other platforms. Hell, they can use the Facebook and Twitter accounts they already have, to distribute their vital and necessary opinions to the rest of us.

If you really believe your opinion has merit, that the conversation needs your voice, and that being able to speak out on issues online is fundamental to our health as a democracy, there’s nothing stopping you from setting up your own media outlet online, and finding others who feel as you do – the internet is particularly good at bringing likeminded people together.

But that’s not how these commentators think. They feel it’s their right to be able to crap over provide their opinions on any piece of content they see online, regardless of whether or not it has anything to do with them. They feel the internet owes them that right, when it’s actually a privilege, and one that can be revoked – as it is being revoked from more and more news websites as of late. They see the web as a form of entertainment, and comments sections as the ability to prove to the world that they have something of value to offer, seeking affirmation and validation from a likeminded community.

The comments on News24, by and large, are self-congratulatory masturbation. People with no ambition saying ugly things about their fellow human beings and getting away with it – all the while, fully believing their actions are completely justified, oblivious to the acrid stench their comments leave on the page, drowning out the voices of compassion and reason.

News24, specifically in the Politics sections, has become our very own /b/. No rules, no regard for decency, a free-for-all where nobody has to take responsibility for what they say. I, for one, am glad it’s on the way out, and I look forward to a better future for news.

Maybe something like this: https://medium.com/matter-driven-narrative/questions-are-the-new-comments-5169d0b2c66f

Outliers in State Healthcare

I was privileged to be able to attend the SciBraai/Code4SA/ICFJ DataQuest event this past Saturday. A simple but effective formula – put a bunch of techies, data scientists and journalists in a room, ply them with coffee and a great braai, and give them free reign on all the data you have – then see what they come up with.

The entire initiative is very inspiring. Code for South Africa has made it their mission to drive data-driven journalism, and the event made it clear that there are stories in our data that the rest of us need to see.

My personal favorite was a project about our dams and water supply in the western cape, visibly illustrating where our water comes from – and it’s not what you think. It was also an eye-opener to learn how far our water supplies have dwindled since last year: the equivalent of 51x the volume of the Cape Town Stadium.

My project took on the healthcare angle. I teamed up with a data scientist who prefers to fly under the radar, and Bibi-Aisha, an eNCA reporter. We made use of the South African Hospitals Survey 2011-2012 data (link) – it was produced by a survey initiative several years ago, and is pretty comprehensive, covering public healthcare facilities right across South Africa.

Comprehensive, and sobering.

Map of SA public healthcare facilities c. 2012

The survey data tracked performance on several points – how often the hospitals were open, how many people were on staff, the leadership and governance, infrastructure, and so on. The facilities were largely self-rated, and a summary “Overall Performance” percentage was calculated for each one.

Survey summary

As far as we could see (and based on the report’s own standards), any hospital scoring 80% or above in the Overall Performance score was well-run. We split the remainder at 0-40% for red, and 41-79% for yellow. The first thing that hit us clear over the head was that only 16% of the facilities in this survey actually passed Government standards.

Of course, the obvious caveat: This data is 3  years old, and things have changed in healthcare since then. Personally I don’t think they could have changed that much, though, given the myriad other issues the Government has had to deal with over the last 3 years.

But there was something else surprising – we started finding outliers. Clinics and hospitals in remote areas, suffering the same issues as their neighbours, and yet were able to report higher scores despite that:

An outlier in the data

An outlier in the data

An outlier in the data

I think there’s a story there. For whatever reason, these facilities are performing better, and they might have lessons to share with the rest of us about how they’re doing it.

Related links:

If you build/clone/enhance/report on any of this, I’d love to hear about it!

Use Amazon S3 for quick-and-dirty MySQL backups

I manage a few basic web applications, and recently had to make a potentially breaking database change. I thought about just dumping out the database to a .sql file so I could restore it later, but then figured I might as well kill two birds with one stone, and solve the problem for good.

The server is a Debian box. I set up a shell script that dumps out a MySQL database, compresses it, and pushes it to Amazon S3. It’s a pretty straightforward setup.

On S3’s side I created a bucket (bucket-name) in the US Standard, then created an IAM user, saved the Access Key and Secret Key, and attached the following Inline Policy:

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Action": [
            "Resource": [
            "Effect": "Allow",
            "Action": [
            "Resource": [

That sets up the user to work specifically with one bucket in your S3 environment. I then installed the s3cmd commandline utility:

sudo apt-get install s3cmd

You need to configure it, which is done interactively:

s3cmd --configure

Once it’s configured, it just takes a basic shell script:


now=$(date +"%Y-%m-%d")

# Dump the file
mysqldump -u username -p password database > ~/backup.sql

# Compress
tar -czvf "$_file" backup.sql

# Push to Amazon
s3cmd put "$_file" s3://bucket-name/"$_file"

# Cleanup
rm "$_file"
rm ~/backup.sql

Set that to chmod +x and you’re good to go! Set that up to run via cron once a day, and maybe configure S3 to only retain the last 28 days of daily backups, and there you have it – instant backup solution, just add water 🙂

Preparing a new Debian 14.04.2 Server for Laravel 5.1

You’re gonna want to put on your admin hat! This guide is written for a new Ubuntu 14.04.2 LTS droplet built on digitalocean.com. We’ll go for repository versions of all these components. First, this guide is 99% accurate for 14.04.2 and will get you Nginx, MySQL and PHP taken care of. Bonus: Jenkins. I love Jenkins, mainly because it’s a one-install server that lets me schedule automated builds and other deployment tasks via my browser. It’s easy to set up, easy to secure, and once it’s set up you may never need to SSH into the server again. Just follow the regular instructions at http://pkg.jenkins-ci.org/debian/ – that will put Jenkins on port 8080, then follow this quick guide to enable some basic security. We’ll need some more software though. This is taken from the list of components that Homestead uses, and all commands are being run as the root user.

apt-get install git redis-server beanstalkd memcached php5-cli php5-mcrypt php5-curl nodejs node-legacyjs npm

An oddity here – you need to manually enable mcrypt before PHP can use it:

php5enmod mcrypt

With that done, install the tools Laravel uses:

npm install -g bower grunt gulp

And last but not least, Composer:

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer

That will add “composer” as a CLI command in one go. So we’ve got a Laravel-capable server now. Let’s get a basic CI pipeline going using Jenkins. We’ll set up something simple that will pull changes from our develop branch into a develop directory on the server, and run any migrations or updates that are required. This is not the best way to handle production releases (you’ll want to use versioned-everything on the server), but it’ll do for a quick setup. Before getting started – database access. Default Laravel 5.1 applications are configured to connect as ‘forge’, to localhost with no password, and use the ‘forge’ database. You might have different details in your project, in which case you’ll need to configure MySQL with matching username, password and database. We’ll just set it up to handle Laravel’s system defaults here:

mysql -uroot -p
Enter password:
create database forge;
grant all on forge.* to 'forge'@'localhost' identified by '';

There’s a little more server-side prep to do – folders and SSH keys. Prepare the folders by ensuring the jenkins user has write access. I prefer having my projects live in a root folder, with symlinks out to the html root:

mkdir -p /projects/project-1/develop
cd /projects
chown -R jenkins:jenkins *

Now set up Jenkins’ SSH key. On the server, run:

su jenkins

Accept all the defaults. That should create a key in /var/lib/jenkins/.ssh/. Run:

cat /var/lib/jenkins/.ssh/id_rsa.pub

Copy the public key. Save it somewhere, if you’re going to use this same server to pull and compile multiple repositories. Right now you’ll just want to add it as a Deployment key under the repository Settings in bitbucket. Finally, we’ll set up the symlink. It’ll be broken until the project itself is checked out for the first time. Start by dropping the default html folder:

cd /var/www
rm -rf html

Now create a symlink that points to where the public subfolder will be:

ln -s /projects/project-1/develop/public/ html

Finally, to Jenkins. We’re going to use the most basic job possible – a straightforward series of commandline instructions. Create a new Freestyle project and give it a name. Under the Build heading, click Add Build Step -> Execute Shell. In there, we’ll just put the commands we would have run ourselves:

# Move to working directory
cd /projects/project-1/develop;

# If artisan exists and composer has run, bring the app down for maintenance
if [ -e artisan ] && [ -d vendor ]; then
    php artisan down

# If we've already cloned, update - otherwise clone from scratch
if [ -e artisan ]; then
    git pull
    git clone -b develop git@bitbucket.org:woganmay/project-1.git .;

# Ensure storage folders are writeable
chmod -R 0777 storage/;

# Run updates and migrations
composer update;
php artisan migrate --force;

# Bring us back out of maintenance mode
php artisan up;

Save the job config and hit Build Now. This will schedule a new job, and then run it immediately, showing the status under the Build History widget. You can view the output of the job as it runs by hovering over the little down arrow by the light, and clicking Console Output: 2015-06-27 21_26_08-planweek.com develop [Jenkins] This will show the raw output from all your commands. It’ll take a while the first time around, as it has to download all the composer packages for the first time. Subsequent runs will be a lot faster as it installs everything from cache. When it’s done you should see something like this towards the bottom of the Console Output: 2015-06-27 21_43_21-planweek.com develop #12 Console [Jenkins] That ‘Finished: SUCCESS’ is what we’re after. That means the project deployed correctly, and you should now be able to browse to it via HTTP. Future deployments can be kicked off by logging into Jenkins and clicking Build Now.

Securing a default Jenkins install

Jenkins has some insanely granular permission controls, but when you install it for the first time, the default is to allow 100% public access to everything. Obviously you’ll want to fix that.

First, click Manage Jenkins, then Configure Global Security. Tick Enable security, then select Jenkins’ own user database, and ensure Allow users to sign up is ticked, and save. We’re leaving Authorization on Anyone can do anything for now.

This will expose the sign up link on the top right:

2015-06-27 20_21_24-Manage Jenkins [Jenkins]

Sign up to create a login for yourself. You’ll be authenticated immediately. Go back to Manage Jenkins -> Configure Global Security, and flip the Authorization switch to Logged-in users can do anything. Save.

So that gives us a sane default – we have basic login control. You might want to disable Allow users to sign up if this instance of Jenkins is internet-facing.

We can go one additional step further – flip Authorization to Matrix-based security. Add your own username to the matrix, select Administer, and save. What this will do is remove ALL the rights Anonymous users have, so where the public might have seen the People list, or the Jobs list, now all an Anonymous user will get is a login prompt.

Youth Day 2016

Quoting the official Government of South Africa website:

In 1975 protests started in African schools after a directive from the then Bantu Education Department that Afrikaans had to be used on an equal basis with English as a language of instruction in secondary schools. The issue, however, was not so much the Afrikaans as the whole system of Bantu education which was characterised by separate schools and universities, poor facilities, overcrowded classrooms and inadequately trained teachers.

So really, not much has changed in the last 40 years, then!

Just something to remember on this, the 39th anniversary of the Soweto Day protests.

Recover Windows 8 Key from BIOS using Linux

Machines that ship with Windows 8 will have the product key written to the ACPI table on your hardware – so even if you reformat, the product key remains embedded in your machine. There are quite a few ways to recover this key if you’re running Windows, but in my case, I had reformatted and installed Ubuntu.

Turns out it’s not a problem. Install the free acpidump utility:

sudo apt-get install acpidump

Then run it with sudo:

sudo acpidump

Then check the output for a block starting with MSDM:


That blurred block there looks very much like a product key to me!