Hello 👋 I'm Dan.

I write PHP, Go, and JavaScript. I also care about web performance.

Donations Now Accepted

For a very, very long time I’ve put off accepting donations to the site, but with Stripe accepting me into their Australian beta, I’ve decided to sign up and see how it goes.

If any of my articles have helped you out and if you’ve got some coin to spare, help a fellow dev/sysadmin out and donate a caffeinated drink or two! Many thanks.

Donate to yes > /dev/null

Installing the APR-based Tomcat Native Library for Jira on Debian 7 (Updated)

If you’re self-hosting Jira on Debian (or another platform, but this post is Debian specific) you might notice in the catalina.log file a line that reports something like this:

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

While this message isn’t a bug per se, but if you’re a completist like me, you’ll want to get it installed to speed up performance for Jira.

First up, you’ll want to install Apache Portable Runtime library along with OpenSSL, if you want to use SSL. Using the command line, we’ll install them with apt-get:

apt-get install libapr1-dev libssl-dev

Go through the process of installing the libraries by following the apt prompts. Note that the version of OpenSSL installed is 1.0.1e, but is patched for CVE-2014-0160 aka Heartbleed).

Next, we’ve got to grab the tomcat native library source tarball (tomcat-native.tar.gz) from Jira so we can compile from source. If you installed Jira from the .bin installer, Jira should be installed at /opt/atlassian/jira. From there, you’ll find the tomcat-native.tar.gz in the bin/ folder (full path: /opt/atlassian/jira/bin). To keep the bin directory clean, we’ll extract the tarball to the home folder of the logged in user:

tar -xzvf tomcat-native.tar.gz -C ~

Now if you cd into the home directory (cd then ls -la) you’ll find a directory called tomcat-native-1.1.29-src. We’ll need to locate the configure script that is some where in that folder. Thankfully, I’ve already done the research for you and it’s in jni/native. cd to that location.

Now that we’ve got the configure script, we need to run the script with the appropriate configuration locations and files. At minimum, you should provide the APR location (--with-apr) and the JVM location (--with-java-home). If you installed APR with apt, the APR config binary will be in /usr/bin/apr-1-config.

Next, the JRE/JDK location. Jira comes with a bundled JRE, but it’s not sufficient for the Tomcat Native Library configurator. If you use the Jira JRE path of /opt/atlassian/jira/jre you’ll get the error checking os_type directory... Cannot find jni_md.h in /opt/atlassian/jira/jre when you run the configuration script. To rectify this, you’ll need the OpenJDK JRE for Linux. Once again, using apt we can install it with ease: apt-get install openjdk-7-jre. After that has completed, if you do find / -name "jni_md.h" you should get something like this:


You can use either file, as a diff shows that both files are the same. With that in mind, our configuration variable --with-java-home can be set to /usr/lib/jvm/java-7-openjdk-amd64. Finally, with SSL support, you can safely set --with-ssl to yes as the configurator can guess the OpenSSL settings. With all that in mind, our final configure string will be as follows:

./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/lib/jvm/java-7-openjdk-amd64 --with-ssl=yes

Hit return and let the configure script finish. Now you can finish it off by making and installing by doing the following: make && make install. As we did not specify an installation prefix, the compiled library will be installed at /usr/local/apr/lib. Jira expects the library to be in one of these folders: /usr/java/packages/lib/amd64, /usr/lib64, /lib64, /lib or /usr/lib. I’m just going to copy them to /usr/java/packages/lib/amd64, do that like so:

cp /usr/lib/* /usr/java/packages/lib/amd64

Now you’re done. Simply start Jira using your prefered method and you should find that APR is being loaded correctly. You can verify this by doing cat /opt/atlassian/jira/logs/catalina.out | grep -A 1 "AprLifecycleListener" and you should see something like this:

Jun 02, 2014 4:23:11 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.29 using APR version 1.4.6.
Jun 02, 2014 4:23:11 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Jun 02, 2014 4:23:11 PM org.apache.catalina.core.AprLifecycleListener initializeSSL
INFO: OpenSSL successfully initialized (OpenSSL 1.0.1e 11 Feb 2013)

Hooray! Jira is running, and it’s loading the Tomcat Native Library with APR successfully!


  • 27/09/2014: updated with newest package name and cp path.

OS X Server and Heartbleed

Heartbleed OS X

If you keep up with technical news you would’ve seen an abundance of articles on something called Heartbleed (or CVE-2014-0160). Essentially, it’s a protocol implementation bug that affects newer versions of OpenSSL, which is used in a majority of Linux installations and can affect many services like Apache, nginx and even IMAP (just to name a few). I’m not going to go into the details because I’ll leave that to the experts, but I highly recommend taking a look at the Heartbleed website to learn more.

Now, when I saw this I got immediately worried about all my clients’ (not to mention my own) installation of OS X Server. Thankfully, OS X has an older implementation of OpenSSL (on 10.9.2 it’s 0.9.8y - found by doing this command in Terminal: openssl version) and according to the Heartbleed website, is not vulnerable. Just to make sure, I ran a Python script found online written by Jared Stafford (download) and when against my server at home, I get the following:

Sending Client Hello...
Waiting for Server Hello...
 ... received message: type = 22, ver = 0301, length = 53
 ... received message: type = 22, ver = 0301, length = 2551
 ... received message: type = 22, ver = 0301, length = 525
 ... received message: type = 22, ver = 0301, length = 4
Sending heartbeat request...
 ... received message: type = 21, ver = 0302, length = 2
Received alert:

Server returned error, likely not vulnerable

Further testing on OS X has revealed that Heartbleed won’t be exposing anything, which is a huge relief for me. Having said that, as this was undiscovered for 2 years, theoretically there’s nothing stopping there being another vulnerability in the wild that could be causing the same (or more or less) damage as Heartbleed.

If you run the Python script and find you are affected, I urge you to patch your OpenSSL installation and regenerate your SSL certificates from scratch. As this vulnerability grabs 64KB worth of data from memory, it’s possible your private key could be in that 64KB. This means you need more than just a CSR, you’ll need to start from the beginning. You can check yourself using an excellent service by Filippo Valsorda.

Good luck out there.

Bryzone - Trial Run / Stargaze

I got an email this morning from Bryzone’s PR team with a link to his debut EP. Normally, when I get a promotional email I tend to ignore them, but with anything music related I got curious. I jumped over to his SoundCloud set page and now I can’t stop listening to it.

I really enjoy Bryzone’s style, it feels similar to Zero T in that it’s almost a blend of chill out/lounge vibes but has the tempo and beats of good old Drum and Bass. The first track, Trial Run, has a great piano melody and Jenny Mayhem’s voice is a killer. I wouldn’t be surprised if she finds herself up there with highly talented DnB vocalists like Diane Charlemagne or Jenna G within a year or two. The second track, Stargaze, has got a real deep house feel - it reminds me of the Jaytech tracks you’d hear on the Anjunadeep label, but instead it also has the backing of a strong DnB groove. Overall, I’m really impressed with his music and I look forward to seeing more of Bryzone in the future.

If you’d like to see more of Bryzone, check out the press release or head over to the SoundCloud EP set page to give it a listen.

I hope to see Bryzone play in Perth, Australia some day because I will definitely be there to watch him groove.

Note: for those who are curious, this was not a payed promotion, I just really like Bryzone’s stuff.

Update: for full disclosures sake, since posting this article I did receive a free copy of the EP from Bryzone’s PR team. Cheers!

Last.fm Album Image Generator

If you didn’t know already, I have run a Last.fm Album Image Generator on my old site for a couple of years now. Recently I started playing with Laravel (FaΓ§ade controversy ho!) and I’ve really loved it, so I decided to port my image generator over to Laravel, and to open source it.

Number 1 Album

The album artwork for Last.fm

Using Laravel has allowed me to make the service a lot easier to develop, and also extend. I’m taking advantage of the logging and caching features in Laravel, along with using plenty of other fantastic packages from Packagist. Overall, I’ve found Laravel has a gentle learning curve (unlike ZF2) and is easy to get started with. I started with Code Bright which was a really good read and gave me a very good head start in developing with Laravel. Of course, the Laravel docs were very useful, along with my friend, Dr. Google.

If you go to http://lastfmalbumimagegenerator.com (and don’t pass any variables in the query string) you’ll be directed to the generator where you can enter your Last.fm username then hit Generate! and you’ll be given BBCode to put on your Last.fm profile page. Pretty simple really!

Here’s an example of the BBCode you’ll get:


If you’re a developer, I invite you to take a look at the code and submit any PRs for fixes, improvements, enhancements etc.

I hope this service works well for you!

Queens of the Stone Age / Nine Inch Nails

QotSA and NIN

Yesterday night I saw Queens of the Stone Age and Nine Inch Nails at Perth Arena in Perth, Western Australia. Last night was the first time I’ve seen either band live, and they were both fantastic! If you, the reader, ever get the opportunity to see either band in concert, I highly recommend it.

I’ve listened to Nine Inch Nails for a few years and never really saw myself as being able to dance along to their music because, let’s be honest, a fair bit of Trent’s music is very mellow and not exactly dance material. Boy was I wrong — I danced the night away.

The warmup act, Brody Dalle, was pretty good. I’ve never heard her stuff before, but I will definitely be checking her out on Spotify.


While the concert was excellent and I loved every song that was played, I do have a favourite song for each set, check ‘em out below:

  • Queens of the Stone Age: A Song for the Dead · Runner Up: Little Sister
  • Nine Inch Nails: Head Like A Hole · Runner Up: March of the Pigs


  • Typical stupid drunk idiot antics like pushing and fighting
  • So many people smoking weed in the arena, I walked out at the end of the night stinking of smoke and pot

Using PHP 5.4 cli on Media Temple's Grid Hosting

I recently ran into a problem on Media Temple’s grid hosting where I couldn’t get Composer to run any post-install-cmd scripts. I was racking my brains on why it would be failing, it was working on my dev environment OK!

Composer error

The Composer error in my Terminal.

The problem was that the PHP binary that is at /usr/bin/php via the cli is 5.3.27, which is below my minimum required version of 5.4. Luckily, a much newer version of PHP (5.5.6 at the time of writing, to be precise) is available at /usr/bin/php-latest. The solution was a two pronged approach.

First off, create a bash profile (or edit an existing one) to have an alias to link php to php-latest. You should SSH into your grid server and enter the following commands:

nano ~/.bash_profile

Now, we’ll add the alias:

alias php="/usr/bin/php-latest"

Exit out of nano by pressing ^X (or Control+X), then hit Y to confirm the changes, then press Return to save your changes to the same filename. Finally, type in the command below to make those changes live (otherwise you’d have to log out/in again to see that alias change):

source ~/.bash_profile

You’ll now notice that if you do php -v you’ll be using the PHP 5.5.6 cli binary. Hooray! But, don’t celebrate yet. If you try to run a Composer post-*-cmd script that requires PHP 5.4 (or greater), it’ll fail. Unfortunately, the commands through Composer don’t seem to be able to pick up the bash alias so we’ll have to manually edit the composer.json file to update the binary paths. Once again, jump back to your SSH session (or you could edit it in a text editor):

Before I continue, the composer.json file I’m using is the one for laravel/framework. So, using nano I’m updating each instance of php in the scripts section of the composer.json file, and replacing them with php-latest.

"scripts": {
  "post-install-cmd": [
    "php-latest artisan clear-compiled",
    "php-latest artisan optimize"
  "post-update-cmd": [
  "php-latest artisan clear-compiled",
  "php-latest artisan optimize"
  "post-create-project-cmd": [
    "php-latest artisan key:generate"

Save and edit, then enter php composer.phar update and watch as Composer downloads, installs and does its post-install optimisations, all withouts errors!

You can now safely kick back with the knowledge that your PHP cli will be running the latest version of PHP (as available from Media Temple).


My iPhone's Home Screen

iPhone Home Screen

My iPhone is very important to me. I use it for hours on end each day, for work and for leisure, so I need the best apps upfront so I can access them quickly.

First off, my wallpaper of choice is a photo of San Francisco that I saw on MG Siegler’s blog, parislemon. Although I’ve never been to San Fran, I love the photo so I put it as my wallpaper. If you like the photo, you can check it out here.

I’m not going to go through every single app I have on my home screen, just a few that I think stand out in particular. So here goes.


  • Website
  • Version at time of writing: 4.3.2
  • Rating: ★ ★ ★ ★ ★
  • Pros: great design, super secure
  • Cons: no iOS 7 design (yep, that’s now a con)

It seems like every day another website or company’s user database is getting exposed. Shockingly, many of them have little to no password obfuscation so hackers have been able to easily pull tens, hundreds, thousands and millions of passwords. 1Password gives you an easy way to generate a complex password, unique for every website or service.

Not only does 1Password generate passwords, but it can also keep other important information secure, for example: credit cards and passport details. You can even store other cards you may have in your wallet, or notes you don’t want to be read by others.

1Password was one of the first apps I ever bought when I got my MacBook Pro in 2009 and I’ve been using it constantly ever since. The ability to have my passwords synced on my Mac, iPhone and iPad all at once gives me an incredible amount of freedom so I can do anything secure-related on the go. One other reason I love 1Password, and the AgileBits team is that they stay on top of password decryption trends. Their cryptography blog is definitely worth a read.


  • Website
  • Version at time of writing: 3.0.7
  • Rating: ★ ★ ★ ★ ★
  • Pros: great looking graphs and statistics
  • Cons: limited range of graphs, not all UI elements entirely obvious

I discovered Analytiks only recently, and it’s hands down the best looking Google Analytics app for iOS that I’ve seen. I really like the percentage increase/decrease statistics it shows each day.

I’ve even found their support to be phenomenal, I emailed them about an issue and got a personal reply in 3 minutes. Issue fixed and I was very satisfied.

One other thing that is really fantastic about this app is that it fully supports Google’s OAuth 2.0 2-step authentication, which is a big plus in my book. It even has a different colour scheme depending on the colour of your iPhone!


  • Website
  • Version at time of writing: 4.2
  • Rating: ★ ★ ★ ★ ★
  • Pros: great design, easy to use
  • Cons: a few minor UI annoyances

A while ago I got really sick of the iOS podcasts implementation (this was when Podcasts were part of the Music.app) so I went to find an alternative. I didn’t really like the look of Downcast (at the time) so Instacast seemed like the perfect replacement, with better features (than the iOS default alternative). Enter Instacast.

Two years later, I still love using Instacast. When iOS 7 landed it was quick to be updated with a new design, which I do like. They’re also one of the only iOS podcast apps that has a Mac companion — and they sync!

I listen to podcasts every night when I head to bed, so it’s fair to say I’ve used it every night for the past two years. I also have a thing for orange, so the icon is really attractive to me.


  • Website
  • Version at time of writing: 2.0.4
  • Rating: ★ ★ ★ ★ ★
  • Pros: super easy to use, great layout
  • Cons: no iPad version

When Fantastical for Mac first came out it felt like a new style of doing calendaring on OS X (and in general). I gave Agenda a go but found its horizontal view scrolling confusing. Enter Fantastical 2.

Fantastical 2 would have to be one of my most favourite apps because it is so well designed and thought out (note I only have 1 con). Jumping to a specific date is very easy, just tap and hold on the date at the top. The day scroller at the top part of the screen (just below the title bar) is very clever, and the way it scrolls along with the list view below is really well done.

Overall, I think Fantastical 2 is a very, very good way to use calendaring on iOS (I rely on it for my work, and life). I just wish there was some way it could integrate with Notification Center, because that kind of sucks.


  • Website
  • Version at time of writing: 3.2
  • Rating: ★ ★ ★ ★ ☆
  • Pros: easy to set up, built-in SSH keeps connections secure
  • Cons: crashes easily, cannot reorder connections list

In my field of work I often need to remote into a server to fix or manage it from afar. Having to fill in VPN connections for each system takes too long, along with jumping between apps to enable VPN for a specific system. Thankfully, VNC over SSH is pretty easy to set up, this is where the power of Screens comes in.

Assuming your server has SSH and VNC enabled, it’s super easy to set up all the details (including transferring over SSH keys if you need them). Having SSH enabled for all my connections means I don’t have to jump between Settings and Screens, and other apps (side note: would love a toggle in Control Center).

There’s also a Mac client for Screens that has iCloud syncing which will keep your settings (excluding passwords) synced between your devices. Overall the program is pretty good, but it crashes quite often when disconnecting from hosts, or when your network configuration changes. Having said that, it’s still a fantastic app.


  • Version at time of writing: 1.008.3
  • Rating: ★ ★ ★ ★ ☆
  • Pros: gorgeous design and very simple
  • Cons: no syncing (yet), no iPad version

When Vesper first launched I was pretty wary of it because it lacked many features that most other note taking apps on iOS have. There’s no syncing, no iPad app, not to mention it’s rather unconventional. Many of those are downsides, but it also removes the complexity that can be found in many text editors.

Using Vesper is pretty simple, the first line is the title, the rest is the body. You can have an image as a header, and you can also associate tags to a note. And that’s about it. At first, many users may be taken back by how “little” there is to this app, but it’s a nice user experience (or UX, to use Louie Mantia’s favourite acronym).

I read Brett Simmons’ blog and he’s detailed quite a lot of the process of designing Vesper’s syncing engine. As a person who is interested in APIs I found his articles very detailed.

Pocket Weather Australia

  • Website
  • Version at time of writing: 4.0.1
  • Rating: ★ ★ ★ ★ ★
  • Pros: great design
  • Cons: none that I can think of

As all Australian residents should know, you can’t rely on iOS’ inbuilt weather app — the only reliable source is the Australian Bureau of Meteorology. Shifty Jelly, the developers of Pocket Weather (or Weather Au as it’s called on the Springboard) have been able to get their hands on the raw data feed of BoM and thus can provide excellent data straight from the experts.

Pocket Weather is a very well designed app that combines the most important information on the main page, but also has loads of secondary information just a slide away. Having the ability to see the rain radar so easily is a huge benefit, especially when the clouds look like they’re about to dump some rain.

They also have a post notification service that can alert you at custom times about the weather. I use this to alert me every day at 7:30 AM so I can plan my clothes for the day. Well, that’s the idea at least. All in all, it’s a fantastic app that all Australians should have!


  • Website
  • Version at time of writing: 2.1.1
  • Rating: ★ ★ ★ ★ ★
  • Pros: nice design and simple gestures
  • Cons: sometimes very slow to receive app updates

Even after the death of Google Reader, Reeder for iOS still lives on! I’m still one of many people who use RSS, and I honestly can’t see myself moving on from RSS for a very long time. Many people have moved on to Twitter for article discovery, and while I agree that it’s decent, it’s still not as good as RSS — my feed is often full of rubbish, even from many people I trust and follow! (Sorry folks)

Thankfully, many services came to the rescue and Feedly became my go to service for RSS. I was very pleased to see that Reeder released a major update (that for a short while was kind of shit) that supports Feedly. Having used Reeder since the 1.x days, I’m really liking the flat design trend that the developer has taken. Although I do miss the updating visuals in the status bar (incidentally, this is the first app I remember seeing that mechanism in), the visuals are terrific and the app is very easy to use.


  • Website
  • Version at time of writing: 3.2.1
  • Rating: ★ ★ ★ ★ ★
  • Pros: nice design and simple gestures
  • Cons: 3.0 removed some features, but they’re slowly coming back

Having been a user of Tapbots apps every since Weightbot first came out I’ve come to really love the robotic designs. Unfortunately iOS 7 pushed Tapbots away from their unique design to become flat and conform with iOS 7’s design. Having said that, it’s still a very well thought out app that satisfies the normal user, along with power users.

The gestures are fantastic and make it really easy to jump quickly around the app. I also really like the ability to customise some of the tabs down the bottom. At first I found how much space each tweet takes up a bit of a nuisance, but I’ve come to love the sparse layout which shows all the information clearly.

If I had one feature request it would be the ability to show all tweets with a picture from a particular user. Tweetbot has a “Recent Photos” section of a user, but as far as I’m aware, there’s no ability to scroll through that list. Other than that, Tweetbot 3 is a fantastic update and is one of the best designed iOS 7 apps around.


  • Website
  • Version at time of writing: 7.3.0
  • Rating: ★ ★ ★ ★ ☆
  • Pros: nice design
  • Cons: semi-unreliable sync, few minor UI glitches

Evernote is one of those services that has been with me for a long time. I’ve used it to log every single bill and payment that I make, copy every receipt I use for warranty or tax purposes or just to catalogue small PDFs I like to read. Upgrading to Premium was a no brainer for me, especially with the search system that uses OCR to find every word in attachments (that’s some super funky NSA shit right there).

I’ve found the app to be pretty reliable, although for a while it was not very obvious how one would create a new text note. Version 7.3 really cleared some things up, although I still find the syncing process to be a bit iffy — I’ve had some items not refresh for a while, and the highlights section show notes from a long time ago.

Even with my few minor gripes, I still find the overall Evernote ecosystem and iOS app to be very good to use.

If you have any apps you love, or you’d like me to review an app, please let me know on Twitter.

P.S. Crunch is an excellent app to pull app icons from the .ipa bundles.

A Simple Way To Display Your Age In PHP

I was quickly updating my website today when I thought of a handy snippet that could be useful for someone. I realised last year when I turned 23 that my website wouldn’t automatically change my age on my birthday (d’uh). It’s only until today that I thought I’d sit down and figure out how to do it in PHP. Turns out, it’s pretty easy.

To do this, we’re going to use the DateTime class (a minimum of PHP 5.3 is required because we’re using the diff function which wasn’t included in 5.2), which is included in PHP and does not require any extra extensions to be installed.

Open up your favourite text editor (in my case, Coda 2). Like I said, using the DateTime class we’re going to create a DateTime object with our birthday, or in this example, the UNIX Epoch (1970-01-01).

$birthday = new DateTime('1970-01-01');

Plainly put, this creates a new DateTime instance with the date 1970-01-01 as the date/time string. Pretty simple so far huh. Now let’s grab the current date/time:

$currentDate = new DateTime('now');

We’re now storing the current date and time ($currentDate) in another DateTime instance. Both of these dates will be calculated with the current PHP timezone, if you need to specify another timezone, you can add an extra parameter with the required timezone. Now, let’s calculate our difference:

$interval = $birthday->diff($currentDate);

Note: you can also skip the current date variable and just enter $interval = $birthday->diff(new DateTime('now'));, but using the separate variable is a bit neater.

If you were to do a print_r of the $interval variable, you’d get the DateInterval object:

DateInterval Object
    [y] => 44
    [m] => 1
    [d] => 17
    [h] => 16
    [i] => 54
    [s] => 7
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 16119
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0

Given that we’re only interested in the year, we can go ahead and use the format function to only output what we want. Examining for PHP.net documentation page (or using the excellent app Dash) you’ll see that there’s a parameter for year, using y.

echo $interval->format('%y');

And you’ll see the following output:


Pretty cool huh? Another example, using the $birthday of 1986-04-20 would get you the result of 27.

All in all, you’re looking at pretty simple code:


$birthday = new DateTime('1986-04-20'); // Enter your birthday in YYYY-MM-DD format
$currentDate = new DateTime('now');

$interval = $birthday->diff($currentDate);

echo $interval->format('%y');

And that’s how you do it.

yes > /dev/null 2.0 Released

yesdevnull 2.0

The website as it appears on a MacBook, iPhone and iPad.

Over the last month I’ve been thinking that my website was ermm… rather shocking on any screen that wasn’t a laptop screen. There was no support for phone or tablet displays, along with no support for retina/HiDPI displays that most smartphones are using these days.

I started off with rebuilding the template from scratch using a flexible and responsive Sass template framework called Gumby. This is my first experience using a CSS extension language and it was pretty fun to play around. I am now very much into mixins and includes.

Next, all site iconography (from Glyphicons) were converted to svg and then entered as code into CSS. I figured that it would be quicker to make big up the CSS file size a bit more than have a few extra HTTP requests for a few small images.

I’ve spent a while testing the site on a staging environment so hopefully it’s working ok for you readers! If you see any issues with the site, please let me know on Twitter at @yesdevnull.