Moving back to a dynamic website
For the past few weeks I’ve been working on converting chameth.com from a static site into a dynamically generated site backed by a database. This is the exact opposite process to one I went through maybe a decade ago. So why the change, and what’s different? I’d actually been toying with the idea of switching for a while. Every now and then I’d have a thought along the lin...
Avoiding the Consequences of Dumb Laws with Tailscale
More and more sites are implementing privacy-invading age checks or just completely blocking the UK thanks to the Online Safety Act. Protecting kids from some content online is certainly a noble goal, but the asinine guidance from Ofcom, threats of absolutely disproportionate fines, and the stupidly broad categories of content have resulted in companies just giving up or going through a tick-box e...
Further Adventures in Music Organisation
I wrote before about how I’d dropped Spotify in favour of locally stored music, but things have advanced a bit since. I had a few issues: Tauon would occasionally manage to lose its database and along with it all my carefully constructed playlists and song ratings, and the experience on my phone was not very fun. I had to manually sync the music by plugging my phone in to the computer, and s...
Blogging and the Imaginary Quality Bar
Recently I realised that I’ve developed a self-imposed quality bar for blog posts. They need to be a certain length, and have a certain substance to them. They need to be generally useful in some way I can’t quite define, to some imagined future audience. They need to have images to break up the page, and opengraph data for when they’re linked to on social media. But… maybe the...
10 Weeks with an Apple Watch 10
Around ten weeks ago I picked up an Apple Watch 10, and have been wearing it almost constantly since. It’s not my first Apple Watch — I had a Series 5 for a bit back in 2020 — but it’s the first time I’ve actually stuck with it. Ten weeks seems like an apt time to reflect on it. Firstly, why did I even bother? Well, for a couple of years I’d been wearing a Xiaomi Smart ...
Making a font of my handwriting
Recently I’ve been on a small campaign to try to make my personal website more… personal. Little ways to make it obvious it’s mine and personal, not just another piece of the boring corporate dystopia that is most of the web these days. I don’t quite want to fully regress to the Geocities era and fill the screen with animated under construction GIFs, but I do want to capture so...
Fixing a loud PSU fan without dying
Three months after I built my new computer, it started annoying me. There would occasionally be a noise that sounded like a fan was catching on a cable, but there weren’t any loose cables to be a problem. Over the course of a few weeks, the sound got progressively worse to the extent that I didn’t want to use the computer without headphones on. I measured the sound at 63 dB, which is a...
Escaping Spotify the hard way
For the longest time I used Spotify for all my music needs. And I listen to a lot of music: sometimes actively, but mostly passively as background noise. I cancelled my premium subscription last December, and stopped using the service entirely. Why? There’s a bunch of reasons. Let’s talk about the money first. Spotify launched at £9.99/month, and stayed that way for over a decade. The...
How tech companies failed to build the Star Trek computer
In most Star Trek series, the ship or station computer is ever-present in the background, waiting to be called on by the main characters. It nearly always does exactly the right thing, and there’s little limit to the functions it can perform. Take this mundane example from DS9:
Finding an awkward bug with Claude Code
I recently encountered a bug in one of my projects that I couldn’t immediately figure out. It was an issue in Centauri, my reverse proxy. After its config was updated, I noticed it stopped serving responses. Looking at the logs, I could see it was obtaining new certificates from Let’s Encrypt for a couple of domains, but I’d designed it so that wouldn’t block requests (or s...
How I use Tailscale
I’ve been using Tailscale for around four years to connect my disparate devices, servers and apps together. I wanted to talk a bit about how I use it, some cool features you might not know about, and some stumbling blocks I encountered. I’m not sure Tailscale needs an introduction for the likely audience of this blog, but I’ll give one anyway. Tailscale is basically a WireGuard o...
The Ethics of LLMs
I’ve written about LLMs a few times recently, carefully dodging the issue of ethics each time. I didn’t want to bog down the other posts with it, and I wanted some time to think over the issues. Now I’ve had time to think, it’s time to remove my head from the sand. There are a lot of different angles to consider, and a lot of it is more nuanced than is often presented. It&r...
If all you have is a hammer…
I presume everyone is familiar with the idiom “if all you have is a hammer, everything looks like a nail”. If not, well, there it is. It’s generally used pejoratively about being single-minded, but I think it also gives a glimpse into something more interesting: mental and perceptual sets. Before I explain, let me tell you a story about a person who bought a 3D printer. When they...
An app can be a ready meal
Three years ago I read “an app can be a home-cooked meal” by Robin Sloan. It’s a great article about how Robin cooked up an app for his family to replace a commercial one that died. It’s been stuck in my head ever since. It’s only recently that I’ve actually done anything like Robin described, though. Part of the reason was my brain got too hung up on the family...
Building a new Computer
I recently built a new computer, after exclusively using a laptop for three years. It’s also the first time I’ve departed from the usual combo of an Intel CPU and Nvidia GPU. While the form factor of a laptop did make it amazingly handy for travelling and attending LAN events, it was starting to show its age and there was basically no sane upgrade path. The main problem was its 3060 mo...
Coming around on LLMs
For a long time I’ve been a sceptic of LLMs and how they’re being used and marketed. I tried ChatGPT when it first launched, and was totally underwhelmed. Don’t get me wrong: I find the technology damn impressive, but I just couldn’t see any use for it. Recently I’ve seen more and more comments along the lines of “people who criticise LLMs haven’t used the...
Home Automation Without the Megacorps
I first experimented with home automation in 2016, by picking up a Samsung “SmartThings” hub. It was terrible. The UI to configure things was slow and clunky, firmware updates were applied whether you wanted them or not, and everything stopped working if their cloud services stopped. You were also locked into whatever integrations they deigned to support, of course. After that broke fo...
The Curse of Knowledge and Blogging
The single worst part about blogging for me is trying to come up with ideas for what to write about. Not because they’re hard to come up with, but because every idea seems too basic or not worth talking about. Seems. It’s not just me, either. My friends will occasionally describe some interesting problem they’ve dealt with, and I’ll chime in with “you should blog abou...
Building a travel toolkit
For a while now, whenever I’ve traveled anywhere I’ve dumped a selection of tools into my backpack just in case I need them. Originally this was mostly focused around being able to open and fix my laptop if anything went wrong, but over time has slowly expanded to include other useful tools. Repeatedly packing these tools and then returning them to where they belonged was tedious, thou...
Simple backups with Restic and Hetzner Cloud
I have a confession: for the past few years I’ve not been backing up any of my computers. Everyone knows that you should do backups, but actually getting around to doing it is another story. Don’t get me wrong: most of my important things are “backed up” by virtue of being committed to remote git repositories, or attached to e-mails, or re-obtainable from the original sourc...
How I Get Things Done
I always quite like reading about how other people do things. What software or hardware they use, or how they manage reminders, todo lists, and so on. I’ve never actually written about how I do any of that, though. So here it is! Productivity In the past I’ve fallen victim to the idea of there being One True Productivity System that would solve all my problems and make me amazing at ge...
Further adventures in 3D printing
Not quite a year ago, I bought a Sovol SV06 3D printer and wrote about my initial experiences. At the end I joked:
A year of boardgames
I realised the other day that it’s a little over a year since I started building out a collection of board games, and thought it’d be fun to go through the collection and what I think about the games in hindsight. The beginning I don’t remember how I discovered the concept of “modern” boardgames, but just over a year ago I purchased Ticket to Ride: Europe as my first....
HTTP/2 and TLS Server Name Indication
I was recently alerted to a bug in Centauri, a simple reverse proxy I wrote. The initial report was that it was serving completely the wrong website, but only sometimes, and it behaved differently in different browsers, and no-one else could reproduce it. I use Centauri for all of my web-facing services (including this site!) so it’s a little surprising such a major bug would have escaped my...
Project log: Filament weight display
One problem I have when 3D printing is that it’s hard to gauge whether there’s enough filament left on a roll to complete a print. Sometimes it’s obvious when the print is small or the roll is full, but often it’s not. If I’m unsure about it, I end up obsessing over the printer instead of just leaving it to do its thing. The typical approach to this problem is to use ...
Adventures in 3D printing
I’d been idly considering getting a 3D printer for a while, but have only recently taken the plunge. I picked up a Sovol SV06 from Amazon for £199.99, which is a model commonly recommended for beginners. About three weeks later, I think I’ve finally finished fixing all the problems the printer has, and thought I’d document them. Setup and out of the box performance The setup of ...
Upgrading the RAM in a Dell G15 laptop
I currently use a Dell G15 laptop for work. It has served me well for a little over a year, but recently it has been struggling a little with my day-to-day workload. It came with 32GB of RAM — the highest possible specification at the time — but that is apparently no longer enough for me. For a recent project, I was working on a Rust library used in an Android app. That meant running the usual...
Generating infinite avatars
I recently added a new ‘about’ section to the top of my website. Like most about pages, it has a picture. Instead of a normal photograph, however, you’ll see an AI-generated avatar. This is admittedly fairly trendy at the minute – apps like Lensa offer to make you profile pictures if you give them a set of photos and some cash – but I’ve done something a bit dif...
Docker reverse proxying, redux
Six years ago, I described my system for configuring a reverse proxy for docker containers. It involved six containers including a key-value store and a webserver. Nothing in that system has persisted to this day. Don’t get me wrong – it worked – but there were a lot of rough edges and areas for improvement. Microservices and their limitations My goal was to follow the UNIX philo...
Adventures in IPv6 routing in Docker
One of the biggest flaws in Docker’s design is that it wasn’t created with IPv6 in mind. Out of the box Docker assigns each container a private IPv4 address, and they won’t be able to reach IPv6-only services. While incoming connections might work, the containers won’t know the correct remote IP address which can cause problems for some applications. This situation is obvio...
Reproducible Builds and Docker Images
Reproducible builds are builds which you are able to reproduce byte-for-byte, given the same source input. Your initial reaction to that statement might be “Aren’t nearly all builds ‘reproducible builds’, then? If I give my compiler a source file it will always give me the same binary, won’t it?” It sounds simple, like it’s something that should just be fu...
Artisanal Docker images
I run a fair number of services as docker containers. Recently, I’ve been moving away from pre-built images pulled from Docker Hub in favour of those I’ve hand-crafted myself. If you’re thinking “that sounds like a lot of effort”, you’re right. It also comes with a number of advantages, though, and has been a fairly fun journey. The problems with Docker Hub and ...
On the utility of user stories
User stories are a staple of most agile methodologies. You’d be hard-pressed to find an experienced software developer that’s not come across them at some point in their career. In case you haven’t, they look something like this:
Reverse engineering an Arctis Pro Wireless Headset
For the last year and a bit, I’ve been using a SteelSeries Arctis Pro Wireless Headset for gaming and talking to friends. It’s a fine headset, but because there’s an always-on receiver there’s no way to detect if the headset is turned on or not from the desktop. Whenever I start using the headset, I set my desktop’s sound to go to the headset, and then when I stop usi...
Apple, Google and aligned incentives
For the past decade I’ve exclusively used Android phones. I got the HTC Dream (aka the T-Mobile G1) shortly after it came out, and dutifully upgraded every 1-2 years. In that timespan I used Android as the basis for my Master’s Thesis, took a job on the Android team at Google, and eventually became a contractor specialising in Android app development. So when I switched to using an iPh...
How to break everything by fuzz testing
Fuzz testing, if you’re not aware, is a form of testing that uses procedurally generated random inputs to see how a program behaves. For instance, if you were fuzz testing a web page renderer you might generate a bunch of HTML - some valid, and some not - and make sure the rendering process didn’t unexpectedly crash. Fuzz testing doesn’t readily lend itself to all types of software, but it p...
An introduction to containers
I’m a huge fan of (software) containers. Most people I know fall in to one of two camps: either they also use, and are fans of, containers, or they haven’t yet really figured them out and view them as some kind of voodoo that they don’t really want or need. I’m writing this short guide to explain a little how containers work - and how running something in a container isn&rs...
Obfuscating Kotlin code with ProGuard
Obfuscating code is the process of modifying source code or build output in order to make it harder for humans to understand. It’s often employed as a tactic to deter reverse engineering of commercial applications or libraries when you have no choice but to ship binaries or byte code. For Android apps, ProGuard is part of the default toolchain and obfuscation is usually only a config switch ...
Debugging beyond the debugger
Most programming – and sysadmin – problems can be debugged in a fairly straight forward manner using logs, print statements, educated guesses, or an actual debugger. Sometimes, though, the problem is more elusive. There’s a wider box of tricks that can be employed in these cases but I’ve not managed to find a nice overview of them, so here’s mine. I’m mainly foc...
Understanding Docker volume mounts
One thing that always confuses me with Docker is how exactly mounting volumes behaves. At a basic level it’s fairly straight forward: you declare a volume in a Dockerfile, and then either explicitly mount something there or docker automatically creates an anonymous volume for you. Done. But it turns out there’s quite a few edge cases… Changing ownership of the folder Perhaps the...
Over-the-top optimisations with Nim
For the past few years I’ve been taking part in Eric Wastl’s Advent of Code, a coding challenge that provides a 2-part problem each day from the 1st of December through to Christmas Day. The puzzles are always interesting — especially as they get progressively harder — and there’s an awesome community of folks that share their solutions in a huge variety of languages. To up t...
DNS-over-TLS on the EdgeRouter Lite
DNS-over-TLS is a fairly recent specification described in RFC7858, which enables DNS clients to communicate with servers over a TLS (encrypted) connection instead of requests and responses being sent in plain text. I won’t ramble on about why it’s a good thing that your ISP, government, or neighbour can’t see your DNS requests… I use an EdgeRouter Lite from Ubiquiti Netwo...
A look at the DNS habits of the top 100k websites
I was thinking about switching DNS providers recently, and found myself whoising random domains and looking at their nameservers. One thing lead to another and I ended up doing a survey of the nameservers of the top 100,000 sites according to Alexa. Most popular providers The top providers by a large margin were, unsurprisingly, Cloudflare and AWS Route 53. Between them they accounted for around 3...
Android testing with Espresso and Spoon
I’ve been spending some time recently setting up automated testing for our collection of Android apps and libraries at work. We have a mixture of unit tests, integration tests, and UI tests for most projects, and getting them all to run reliably and automatically has posed some interesting challenges. Running tests on multiple devices using Spoon Spoon is a tool developed by Square that hand...
Shoring up SSHd configuration
I recently came across a useful tool on GitHub called ssh-audit. It’s a small Python script that connects to an SSH server, gathers a bunch of information, and then highlights any problems it has detected. The problems it reports range from potentially weak algorithms right up to know remote code execution vulnerabilities. This is the kind of output you get when running ssh-audit. In this pa...
Creating an offline GnuPG master key with Yubikey-stored subkeys
I recently noticed that I’d accidentally lost my previous GPG private key — whoops. It was on a drive that I’d since formatted and used for a fair amount of time, so there’s no hope of getting it back (but, on the plus side, there’s also no risk of anyone else getting their hands on it). I could have created a new one in a few seconds and been done with it, but I decided ...
Why you should be using HTTPS
One of my favourite hobbyhorses recently has been the use of HTTPS, or lack thereof. HTTPS is the thing that makes the little padlock appear in your browser, and has existed for over 20 years. In the past, that little padlock was the exclusive preserve of banks and other ‘high security’ establishments; over time its use has gradually expanded to most (but not all) websites that handle ...
Automatic reverse proxying with Docker and nginx
Over the past few weeks I’ve gradually been migrating services from running in LXC containers to Docker containers. It takes a while to get into the right mindset for Docker - thinking of containers as basically immutable - especially when you’re coming from a background of running things without containers, or in “full” VM-like containers. Once you’ve got your head a...
Monitoring power draw with WeMo Insight Switches
I recently picked up a couple of Belkin’s WeMo Insight Switches to monitor power usage for my PC and networking equipment. WeMo is Belkin’s home automation brand, and the switches allow you to toggle power on and off with an app, and monitor power usage. The WeMo Android app is pretty dismal. It’s slow, doesn’t look great, and crashed about a dozen times during the setup pr...
Reverse engineering the Sense API
Sense is a little device that sits by your bedside and, in conjunction with a little ‘pill’ attached to your pillow, monitors your sleeping patterns and any environmental conditions that might hamper them. Android and iOS apps show you your sleep history, and offer suggestions for improvements. Sense was Kickstarted in August 2014, raising over 2.4 million US dollars, and shipped to ba...