Categories
2026
Why I still write code
By any sensible reading of an org chart, I have no business being in this file. I’m a Head of Software Engineering. My calendar reckons I should be in a room somewhere talking about headcount and roadmaps. Instead it’s …

A signature the platform can't forge
A self-updating tool has a chicken-and-egg problem baked into it. The thing doing the updating is the thing being updated, so when it reaches out and pulls down a newer version of itself, it’s the one that has to decide …

Anything under an 8
I read the news about the National Vulnerability Database over a coffee that went cold while I sat there muttering at my phone. The short version: the NVD, the free public catalogue that quietly props up half the …

The consent you can't ask for
There’s a comfortable story going round about telemetry, and it goes like this. There are two kinds. There’s the creepy kind, the usage data a vendor harvests to work out who you are and what you do, and that kind needs …

Three traps release-plz sets for a Rust workspace
I wrote up the two days I lost releasing a seventeen-crate workspace to crates.io as a war story, wrong turns and all. This is the other half: the field guide, so you don’t have to lose the same two days. release-plz is …

Telemetry that asks, and telemetry that doesn't
go-tool-base has had a thing called telemetry for a long while now. It’s the opt-in kind: the product analytics that asks a user’s permission before it phones a single byte home, sits there as a no-op until they say yes, …

Same config, two answers
Let me confess a small heresy first, because it’s the reason any of this happened. After a career spent as a branching man, gitflow, gitlabflow, a tidy develop branch and a careful dance of merges, I’ve come round to …

Building a web service with go-tool-base, part 6: seeing what your service is doing
On paper the macguffin service is finished. Part 5 left it typed, fast, documented and served over TLS. So you deploy it, traffic starts flowing, and a week later someone wanders over to say “it’s slow”. Slow how? Slow …

The security service I had to switch off
A while back I wrote about hardening the account that would hold the signing key, and one line in it has aged badly. “GuardDuty is already looking,” I wrote: the account watched from day one, threat detection on before …

From allow_failure to blocking
There’s a special kind of CI job that everyone on a team quietly learns to ignore: the one marked allow_failure: true. It runs, it goes red, the pipeline goes green anyway, and after the third time you stop looking at …

Building a web service with go-tool-base, part 5: docs that write themselves
The google.api.http annotations we added in part 4 have done one job so far: they told the gateway which REST calls map to which RPCs. But they describe the API precisely, the paths, the verbs, the request and response …

Nobody's coming to clean your supply chain
Pick a week in May 2026 and there’s a supply-chain attack in it. On the 11th someone owned TanStack’s CI and pushed 84 poisoned package versions in six minutes. On the 14th, three malicious versions of node-ipc, a …

Building a web service with go-tool-base, part 4: REST for free, with the gateway
A quick tally of where part 3 left us. One domain, the Store. One gRPC service over it, mapping the domain to proto with toProto. And then a whole second transport, the REST layer, with its own routing and its own toDTO …

Building a web service with go-tool-base, part 3.5: the same server, now a website
The HTTP server from part 3 serves JSON. But net/http doesn’t care what you hand it: HTML, an image, a stylesheet, a whole little site, it’s all just bytes with a content type. So before we get back to the API in part 4, …

The greybeards' edge was never typing
I have a retirement plan, and it is gloriously low-tech. A cabin, some trees, a woodstove, and a firm rule that no wifi symbol ever appears within a mile of me again. I think about it more than is probably healthy. …

Building a web service with go-tool-base, part 3: a REST service, by hand and by spec
The gRPC service from part 2 is the right core for service-to-service traffic. It is also useless to a great many of the things that might want to call it: a browser, a webhook from some SaaS, a partner who will not …

Building a web service with go-tool-base, part 2: a gRPC service, with TLS
The heartbeat from part 1 runs, ticks along, and shuts down politely when you ask it to. It also talks to absolutely no one. A service people can actually call needs an API, and for a typed, fast, streaming-capable one, …

AI didn't kill curl's bug bounty. The bounty did.
In January, Daniel Stenberg shut down curl’s bug bounty. The headlines wrote themselves, and they all said the same thing: AI killed it. A flood of machine-generated slop drowned the maintainers, so they pulled the plug. …

Building a web service with go-tool-base, part 1: lifecycle and graceful shutdown
A CLI does its job and gets out of the way. You run it, it prints something or writes a file, the process exits, done. Then one day you want the opposite: a thing that stays running. A server answering requests, a worker …

Building a CLI with go-tool-base, part 5: a CLI that updates itself
You ship version one. A week later someone finds a bug, you fix it, you cut version two. Now for the awkward part: how does the person who installed version one ever get version two? Email them? Hope they wander back to …

Building a CLI with go-tool-base, part 4: an AI dungeon master
I run a Dungeons & Dragons game on the odd weekend, so when I sat down to put an AI feature inside a CLI, my first instinct wasn’t a chatbot. It was: could the tool run a little adventure, with an AI as the dungeon …

Technical CV writing is still hard, and now a robot reads it first
Seven years ago I wrote a post called Technical CV writing is hard, pulled my own CV apart, and explained every choice in it. I even bragged that it converted to a first interview about eighty per cent of the time, then …

Building a CLI with go-tool-base, part 3: expose your CLI to AI agents
“Make it work with AI” is the request that lands on your desk with a thud and no further detail. The first time it landed on mine I braced for a treadmill of integration work: an adapter for this assistant, a wrapper for …

Moving this blog off Jekyll
The blog you’re reading used to be a Jekyll site on GitHub Pages, built on the lovely beautiful-jekyll theme. It isn’t any more: it’s Hugo now, published to GitLab Pages. The hosting move rode along with go-tool-base …

Building a CLI with go-tool-base, part 2: configuration your tool can trust
In part 1 you scaffolded a tool and gave it a hello command. It says the same thing every time, which is fine for a first command and useless for a real one. The moment a tool does anything worth doing it needs settings: …

Two bugs that taught me the rules
Some bugs are interesting because they’re subtle. These two were interesting because they were the exact opposite… in each case the tool had a hard rule I simply didn’t know about, and its error message couldn’t be …

Building a CLI with go-tool-base, part 1: scaffold and your first command
Every time I start a new Go CLI, the first hour goes the same way, and none of it is the actual tool. Config loading. A logger. An update command. An error path that prints something a human can act on. A help system. I …

Reviewed, then applied
The genuinely dangerous moment in infrastructure-as-code isn’t the apply. It’s the gap between the plan a human read and approved, and the change that actually runs a moment later. If those two are different computations …

One graph, not micro-stacks
Once an infrastructure repo has a few concerns in it (account hardening, the security baseline, the signing stack still to come) there’s a steady pressure to split them into separate stacks with separate state, and …

CI you include, not copy
Every infrastructure repo runs the same CI: lint the OpenTofu, scan it, validate it, plan, apply. The first repo, you write that .gitlab-ci.yml by hand. The second, you copy it. By the third, you’ve got three copies of …

One image for the whole toolchain
Every CI gate job across the infrastructure repos reaches for the same pile of tools: OpenTofu, tflint, trivy, checkov, gitleaks, terraform-docs, the AWS CLI. Installing that pile per job is both slow and quietly …

A 403 you can't fix in IAM
The OIDC post explained the handshake that lets a GitLab pipeline deploy to AWS with no stored key. This is the story of the first time I got it wrong, and spent an afternoon fixing the wrong thing. The error was a flat …

Pure-Rust Git, no git binary
go-tool-base’s VCS support has two halves that get confused for one. One half talks to forge APIs (GitHub, GitLab) for releases and pull requests. The other talks to the .git directory on disk: clone, history, diff, …

Routing security findings without the noise
Turning on GuardDuty and Security Hub gives you threat detection. It also gives you a firehose. And an alert system that dutifully forwards everything in that firehose isn’t monitoring, it’s a very efficient way of …

Why go-tool-base left GitHub for GitLab
A botched version bump made me stop and actually look at where go-tool-base lived, and I didn’t much like what I saw. GitHub had spent months quietly falling over, and when Mitchell Hashimoto (GitHub user #1299, no less) …

Why I hand-rolled every module
There are well-known community module libraries for AWS: Cloud Posse, the terraform-aws-modules collection, plenty more. Both terraform-aws-bootstrap and terraform-aws-security-baseline use almost none of them. Every …

Hardening the account that will hold the keys
Bootstrapping the account got it ready: somewhere to store state, an identity to deploy as, enough for the next tofu apply to run. Ready is not the same as safe. An account with no audit trail, nothing watching it, and …

Two layers of tags, and which one wins
Tagging cloud resources is one of those jobs that’s trivial to do badly and surprisingly fiddly to do well. Everyone agrees resources should be tagged. The argument nobody quite has out loud is where the tags should come …

No access keys in CI
A long-lived AWS access key, sitting in a CI system, is just about the single credential I’d most like to be rid of. It’s powerful, it never expires unless someone remembers to rotate it (nobody remembers to rotate it), …

clap's global flag, except in a passthrough subtree
--output json worked everywhere. On the top-level command, on every ordinary subcommand, wherever the user fancied putting it. Then it stopped working in exactly one place, and of course it was the subcommand I’d been …

The chicken-and-egg of remote state
Here’s a puzzle that every infrastructure-as-code setup hits exactly once, right at the very beginning, and then never again. An OpenTofu stack stores its state in a backend. The bootstrap stack I wrote about last time …

Secrets that scrub themselves from RAM
A while ago I worked out where a CLI should keep your API key: env var, OS keychain, or, grudgingly, a literal in the config file. That answers where the secret lives. It says nothing about what happens to it once it’s …

The cleanup tool that almost deleted its own hands
The first time I pointed aws-nuke at a real account, the dry-run printed hundreds of lines of angry red text and my stomach dropped. Then I read it properly, and two things turned out to be true at once. Almost all of …

The security finding you must not fix
A security scanner flagged a finding in my Terraform, and the correct response, the one I had to talk myself into, was to leave it exactly as it was. Not because the finding was wrong about what the code did. It was …

Two telemetry events, one mangled line
A line in a log file that no parser would touch. Not a wrong value, not a missing field. Half of one telemetry event spliced into the middle of another, like two people typing into the same text box at once. Which, it …

Supporting a provider, or actually using it
If your CLI tool talks to an AI model, you don’t want to hard-wire one vendor. So you reach for a single client interface over several providers, which is the right call. The trap is the next step: build that interface …

A state bucket that defends itself
OpenTofu’s remote state file is, quietly, the most sensitive thing in an infrastructure repo. It’s a plain JSON document listing every resource you manage, every ID, and, depending on your providers, the odd secret in …

The bootstrap that does almost nothing
A brand-new AWS account is a slightly nerve-wracking thing. It can do almost anything, it’s hardened against almost nothing, and the list of stuff you ought to set up before you trust it with anything real is long. The …

Errors without an error handler
In the porting post I said go-tool-base’s error handler was one of the bits that didn’t survive the move to Rust, and promised to come back to it. Here’s the come-back. The short version is that Rust hands you, for free, …

Two kinds of feature flag
go-tool-base has feature flags: switches that decide which built-in commands are live in a given run. rust-tool-base has those too. But it also has a second, completely separate kind of flag, and the difference between …

forbid means forbid, until linkme needs a word
There’s a line at the top of every production crate in rust-tool-base that I’m quietly proud of: #![forbid(unsafe_code)]. And there are a couple of files that have to say #![allow(unsafe_code)] instead. Not because I …

A framework that contains no unsafe
“It’s written in Rust” gets thrown around as if it were a memory-safety guarantee. It mostly isn’t. Rust is memory-safe by default, which is a wonderful thing, but the unsafe keyword exists precisely so any crate, any …

Reloading config without a restart
A config file changes. Someone edits a setting, rotates a credential, flips a feature flag. How does the running process find out? For most processes the answer is blunt: it doesn’t, until you restart it. For a …

Waivers with an expiry date
A vulnerability scanner gives you a yes or a no. Is there a known advisory on a path you actually use? Yes, or no. That’s genuinely useful, and you should run one. But it’s a snapshot, taken on the day you ask, and …

A signing key needs somewhere to live
I left a door open a couple of posts ago, and it’s been quietly bothering me ever since. When I wrote about verifying your own downloads, I was honest that a checksum sitting next to the binary only catches accidents. …

Process isolation won't save you from the filesystem
A test that passed every single time I ran it on its own, and failed maybe one run in five when I ran the whole suite. The failure was always the same: the self-update test downloaded a release archive, went to extract …

A builder that won't compile if you forget a field
go-tool-base configures things with functional options, and if you forget a required one, the best case is a runtime failure and the worst case is an empty value sailing silently into everything downstream. Most builder …

Verifying your own downloads: how I solved it for self-updating CLI tools
Way back in the introduction I promised I’d come back to the self-update integrity checks. Here we are. And the starting point is a slightly uncomfortable admission: for a good long while, go-tool-base’s update command …

Registering commands without life before main
I ended the last post promising to show how a Rust command registers itself when the language flatly refuses to run any of your code before main(). This is that post, and it’s a lovely example of reaching the same …

What survives a port, and what doesn't
Rebuilding go-tool-base in Rust turned out to be the most honest design review I’ve ever sat through, and I didn’t have to do anything except keep going. Porting a framework into a language with completely different …

Two API decisions that quietly contradict each other
Two design decisions on one enum, each sensible on its own, that would have quietly fought each other if I’d let them. I didn’t, but only because the second one is easy to get wrong and the compiler wouldn’t have said a …

The blank import that keeps a dependency out of your binary
go-tool-base can stash your credentials in the OS keychain, which most people building on it are perfectly happy about. But some of them ship into regulated and air-gapped environments where the binary isn’t permitted to …

rust-tool-base: the same idea, in a language that argues back
I built go-tool-base because I was sick of rebuilding the same CLI scaffolding every time I started a new Go tool. You’d think that would have taught me a lesson about doing things more than once. Apparently not, because …

Just enough Rust to follow along
I’m about to write a run of posts about building rust-tool-base, and they lean on a handful of Rust ideas that I’d otherwise have to keep stopping to explain. So here they are, up front, in one place. You don’t need to …

Where should a CLI keep your API keys?
Your CLI tool needs the user’s API key. It has to come from somewhere, and it has to survive between runs, so the obvious move is to ask once and write it into the config file. One tidy api_key: line. Job done. It works …

A configurable AI endpoint is an attack surface
“Let users point at their own AI endpoint” is one of those config options that looks completely harmless on the way in. People want it, for perfectly good reasons. Then you sit with it for a minute and realise you’ve …

Redacting the secret you didn't know was in the string
Dammit! How did that get there? A log line that should never have existed. Not a password I’d carelessly printed, nothing as obvious as that. An upstream API handed me back an error, and it had quoted my own bearer token …

I had the framework audited: every finding was the same shape
When a real security audit lands back in your inbox, the temptation is to read it as a shopping list of unrelated mistakes. Fix one, fix the next, tick them off, move on. I did exactly that the first time. The second …

The test-mocking pattern that races
I’m going to tell you about a bug go-tool-base shipped, because it’s one of those bugs that’s so reasonable-looking you’ll find it in textbooks, conference talks, and an awful lot of otherwise excellent Go code. We had …

A mutex on a flag nobody writes twice
“Why is there a mutex around a boolean that only ever gets set once?” It’s a fair question, and I’d half-asked it of myself before someone asked it of me. The answer turns out to be written, in as many words, in a code …

OpenSSF Scorecard graded my supply chain
I turned OpenSSF Scorecard on expecting a pat on the head. go-tool-base is a security-minded project, I’m careful, surely the robot would agree. The robot did not agree. It handed back a report card with a fair bit of …

Testing code that calls an LLM: yes, you actually can
“You can’t test code that calls an AI.” I’ve heard it said with great confidence, and it’s half right, which is the most dangerous kind of right. You genuinely can’t assert on what a non-deterministic model says. But the …

The AI provider that isn't an API
go-tool-base’s chat package puts five AI providers behind one interface. Four of them are exactly what you’d guess: HTTP calls to OpenAI, Claude, Gemini, and anything OpenAI-compatible. The fifth one isn’t an API at all. …

AI conversations you can resume
An AI conversation is, fundamentally, its own history. The model’s next answer depends on everything said so far. And a CLI tool, by its very nature, forgets everything the moment it exits. Put those two facts together …

An AI agent that has to make the build pass
Most AI code generation works on a charming little principle I’ll call generate-and-hope. The model writes the code, the model stops at the closing brace, and whether the thing actually compiles is left as an exercise …

Stop regex-ing the LLM's prose
Ask an LLM a question and it hands you back prose. Lovely to read, miserable to program against. You wanted the one number buried in the middle of it, and now you’re writing a regular expression to fish a word out of …

Telemetry that asks first
Usage telemetry is genuinely useful. Knowing which commands people actually run, where the errors cluster, whether anyone ever touched the feature you spent a fortnight on… that’s the stuff that makes you a better …

Nobody reads the manual
Let me describe the actual lifecycle of a user meeting your CLI tool, because it’s a bit humbling. They run it. It doesn’t quite do what they expected. They run it again with --help. They get a wall of monospaced flag …

Letting the AI call your Go functions
An AI that can only produce text can describe your system. An AI that can call your Go functions can actually operate it. That gap, between describing and doing, is the difference between a chatbot and something …

BDD where it earns its place, and nowhere else
I have a slightly complicated relationship with BDD. I’ve watched it turn a tangled test suite into something the whole team could read and reason about, and I’ve watched it turn a perfectly good unit test into a …

The config key that quietly did nothing
I once spent the better part of an hour convinced a timeout setting was broken. I’d set it in the config file, the tool ignored it, and the code that read it looked perfectly correct. The setting was tiemout. I’d typed …

An AI interface that fits on one screen
The moment you decide a CLI tool should talk to an LLM, there’s a strong gravitational pull towards reaching for LangChain, or one of its many relatives. It’s the obvious move. It’s also, for most CLI work, a bit like …

One variadic, and I'd already spent it
I had a constructor I was rather pleased with. Hand go-tool-base’s root command its props and as many sub-commands as you like, and off it goes. Then I needed to thread some config file paths through it, reached for the …

Half your users don't have eyes
Run a command in your favourite CLI tool and look at what comes back. Colour. Neatly aligned columns. A friendly little summary sentence. Lovely… if you happen to be a human with eyes. But a good half of any tool’s users …

Middleware for CLI commands, not just web servers
Every CLI tool past a certain size grows a category of logic that doesn’t really belong to any one command, and yet has to happen for loads of them. Timing. An auth check. Panic recovery, so a crash becomes a clean error …

Lifecycle management for when your CLI grows up into a service
There’s a moment in the life of a lot of CLI tools where they stop being a CLI tool. Nobody quite decides it. It just happens. Someone needs the thing to also expose a little HTTP endpoint, or poll a queue, or run a …

A logging interface that doesn't leak its backend
The same tool, in two different lives, wants two completely different kinds of log. On my laptop I want logs I can actually read: colour, alignment, friendly timestamps. The very same tool running as a daemon in a …

Errors that tell the user what to do next
Here’s an error message I’ve been on the receiving end of more times than I’d care to count: error: failed to read config file True. Also completely useless! I now know something is broken and I haven’t the faintest idea …

Props: the container that does the heavy lifting
I name-dropped Props back in the introduction and then rather glossed over it, which was a bit unfair of me, because it’s the single most important design decision in the whole framework. So let’s give it the attention …

Many embedded filesystems, one merged view
Go’s embed package is one of those features that makes you slightly giddy the first time you use it. One //go:embed directive and your default config, your templates, your docs are all baked into the binary. The tool …

Scaffolding that respects your edits
When I introduced go-tool-base I made a passing promise to come back to “the generator that won’t clobber your edits”. This is me keeping it, partly because it’s the feature I’m quietly most proud of, and partly because …

Design your whole CLI in one file
Here’s a question that sounds trivial and really isn’t: where, exactly, does a CLI tool’s structure live? Not the logic of each command… the structure. Which commands exist, what they’re called, which flags they take, …

Your CLI is already an AI tool
“Make it work with AI” has become one of those requests that lands on a developer’s desk with a thud and not much further detail attached. My instinct, the first time, was to brace for a big lump of integration work… a …

go-tool-base: I got tired of reinventing the wheel
If you’ve written more than two or three command-line tools in Go, you’ll recognise the shape of the first afternoon. I certainly do! You reach for Cobra for the command tree, Viper for config, and then you start the …

2020
Migrating away from Mediawiki and how to export its data
I like Mediawiki, it is a simple tool capable of doing a lot and can be very flexible and easy to customise. However its not always the right solution! I had a situation where we needed to migrate away from using it for …
Pre-populating Neo4J using Kubernetes Init Containers and neo4j-admin import
Recently there has been an uptake in the use of Neo4j by the Data Scientists. This is a good thing! they are wanting to use the right tool for the job. However we need to run it inside our k8s cluster as a portable …

Adding Ambient Sounds to your Discord Server On LInux
I’m a Dungeon Master! I don’t mean that in the S&M sense! As in the game Dungeons & Dragons (https://dnd.wizards.com), where I run a weekly game as well as take part in a couple of campaigns as a player. It’s a lot of …

Encrypting additional drives with LUKS on Linux
Encryption is king nowadays with everyone having mobile devices. We have a significant number of people on laptops that travel around and also workstations that live in open plan offices. This means we encrypt all of our …

2019
Connecting to Ubuntu 18.04+ using RDP
We have a mix of different setups that the Software Engineer and Data Scientists use to get their work done. There are some using just Linux on laptops, Some on MacBooks and some on the various versions of Windows. For …
Technical CV writing is hard
Recruiting people is effing hard! That’s all… I’ll get back to reading through CVs now and let you get on with your day! Medicines Discovery Catapult is, at the time of writing, recruiting Software Engineers, and as …

Dell DisplayLink D6000 & Ubuntu 18.04+ Issues
I love Ubuntu… I’m pretty fond of dell kit too! So I was rather chuffed when I started working at Medicines Discovery Catapult because they let me have both. When you look at my desk it looks like it could be an advert …

Project Slayer: The Critical Path
The first of my new round of talk abstracts! In all honesty this isn’t a talk but something more that came out of a very drunken Saturday night at #phpbnl19. There were a bunch of us sat talking and somehow the topic of …

A reboot and a legacy moniker
So… my last post was a good 2 years ago now…. Hi how have you been? It’s been a very busy couple of years with a lot of stuff shifting in my personal life meaning things inevitably take a back seat. However its been long …
2016
Monty Python explains why your project failed!
As part of the attempt to develop my profile as a speaker, I’ve realised that I sometimes need to explain a few of my current talk abstracts a bit too much. This is mainly due to my lack of experience writing them and …

Using Gmail aliases with Evolution
If your anything like me you have a large number of email aliases that you use with Gmail which is great. However I use Evolution as a mail client more often than not when using Gnome3 as a desktop. It’s very easy to set …
Are you a Good Code Scout? - NomadPHP lightning talk video
https://www.youtube.com/watch?v=Tt0lnauF5lI Just before the Christmas period I was lucky enough to be able to give my “Are you a good Code Scout?” talk as a lightning talk for NomadPHP. Here is the video that was …
2015
A metaphor about PSR-7 and Middleware for non-developers
Never one to shy away from coming up with a metaphor for explaining something technical I found myself having to come up with one on the spot for PSR-7 and Middleware while at the recent PHPNW15 Conference. Normally my …

Wow... What a Conference
So I attended the PHPNW15 conference this weekend and what a weekend. I’ve been an attendee of the conference for a number of years and have always enjoyed it immensely. However this year turned out to be something …
Badges & Stickers
One of the most prominent things I’ve been asked about regarding my promoting being a Good Code Scout, is where can we get the badges? Following on from a number of questions and subsequent tweets about it …

What is a PHP Scout
Recently I’ve had a lot of people asking me what a PHP Scout is! I thought it would be a good opportunity to explain. To understand what a PHP Scout is it helps to know a little of the background basics of Scouting in …
The PHP Scout Membership Badge
As the PHP Boy Scout I’m having some badges made and I wanted to introduce the all new PHP Scout Membership Badge.

My first ever public appearance as PHPBoyScout
So it’s finally happened! I stood up in front of a group of developers and gave a lightning talk about how Scouting Principles should be applied to every day development. [slideshare …

Goodbye Dev in Charge
Over all the time that I’ve been a developer I’ve had people telling me that I should get in front of an audience and speak. However I’ve always suffered from a rather bad case of ‘Imposter Syndrome’ which meant my …
Free Open Source Website for Scouts
I’ve been a Scout Leader for a few years now and the District I work within have very little by way of internet presence. As a bit of a pet project I started building a simple Scout based website for them to use.

2013
Flexbox cross browser
Despite having been around for a while and having been through a couple of revisions, its support across browsers can vary greatly. From “Candidate Recommendation” on Chrome/Opera, “legacy flexbox” on Firefox and no …
Disabling Cache in Silverstripe 3.1
While working with Silverstripe we found ourselves having to run “?flush=1” a lot to clear the Cache. To switch it off, while you work, add the following to your mysite/_config.php: …
Creating Custom Routes in Silverstripe 3.1
We wanted to create a Route to our custom Products Controller in our products module for SilverStripe 3.1, such as: “http://www.examplesite.com/products/” However looking at the Controller Documentation it was not clear …
Set up SilverStripe 3.1 using only Git (No Composer)
We recently tried to use composer to set up SilverStripe 3.1, but ended up with a dependency nightmare. In order to work around this we decided to make use of Git submodules. First set up your Git repository and run: git …
Enabling MYSQL_CLIENT_INTERACTIVE with Doctrine 2 on Rackspace Cloud Database
We recently ran into problem using Doctrine 2 connecting to a Rackspace Cloud Database using the MySqli Driver. Problem: We have a long running PHP script that can sometimes run for hours at a time whilst processing …
Installing PECL extensions for Zend Server 6
Recently we have revisited using Zend Server for some of our projects and decided to give the new version 6 a chance to prove itself. Overall its a big improvement over version 5. There are still some things that are …
Better Output for MySQL Select Command Using \G
If you ever find yourself using MySQL via command line and end up with something like this: And thought there must be another way, well here it is: Use \G instead of ; at the end of your select command. For example: …
Introducing ZuQ - A Simple ZeroMQ Queuing Daemon
We recently had the need to create a queuing system to replace an implementation of RabbitMQ that was being used on a previous project. The reasoning behind this is that the requirements of the project required a very …
Glorious Gluster - How to setup GlusterFS on Rackspace Cloud and Ubuntu 12.10
A few of our projects recently called for a distributed file-system that provided high availability and redundancy. After a tip off from a fellow techie and a quick browse around the net it appeared that a solution …
Docblock, Oh Docblock, wherefore art thou Docblock (hint: Zend Optimizer Plus lost them)
tl;dr> I make a terrible assumption about Zend Optimizer+ and am corrected by Dominic in the comments; Terrible post title I know but its the best I could come up with. I’ve just come up for air after spending the …
Our Redmine install died, We all cried!
We have been using redmine for quite a long time and a few months ago attempted to upgrade from 1.3 to 2.something. Unfortunately I (quite typically) borked the installation and since then its been hobbling along after …
Quick and easy setup of and connection to NRPE on Ubuntu
About NRPE NRPE (Nagios Remote Plugin Executor) is a useful tool that allows you to execute scripts on remote servers and return the output for ingestion by some form of monitoring software. Setup We currently have our …
Debug PHP CLI on Remote Server with Xdebug and PHPStorm
This was a head scratcher when I ran into this yesterday and I thought I would share my solution to the following scenario: I need to debug PHP Command Line script, located on Remote LAMP Virtual WebServer running in …
2012
Compiling PHP 5.4 on Ubuntu 12.04
So recently I’ve been working with PHP 5.4 a LOT. Unfortunately Ubuntu (my main dev environment) is behind the times. So I’m resorting to compiling PHP manually. Not a daunting as it may first appear. The really tricky …
Compiling Apache 2.4 on Ubuntu 12.04
I’ve decided that I need to up my game when it comes to webservers. However I’m not yet ready to switch to Nginx or one of the other webservers out in the wild as I need something up and running rapidly. Granted the …
Rsync and custom SSH commands
Rsync is a great tool but can be a pain if you have to jump through hoops to connect via ssh such as connecting via a different port. A simple solution is to use the -e flag (also knows as –rsh=COMMAND). This flag allows …
Nice New Nexus7
This morning I woke up to an email telling me that my Nexus7 that I had ordered 3 weeks ago was… “out for delivery”. I couldn’t contain my excitement. I sat patiently waiting by my door. Finally 11 o’clock rolls around …

Registering custom view helpers in ZF2
If you want to register custom view helpers with a module you can do so by using the service location built into the Skeleton Application and creating a module config that looks something like. return array( …
Bootstrapping ZF2 Forms
So… With the release of beta 5 for Zend Framework 2 I thought it time for me to tidy up and fix a few modules I created back at beta 3. Now I’m a big fan of Twitter Bootstrap CSS framework as I’m sure a lot of other …
Loaded Testing
I recently had to do some load testing for a site recently that would allow me to test in excess of 100k requests in a 60 second period… So I decided to do some testing using JMeter as it seemed like a suitable tool for …