For the past three years, I’ve been writing year-end reviews to look back upon the year that had gone by and reflect on what had happened. As yet another year has gone by, it is time to continue the tradition.

Like last year, I’ll divide this into several areas, as opposed to grouping by month as I had done in the years before:

  1. BGP and operating my own autonomous system;
  2. My homebrew CDN for this blog;
  3. My home server;
  4. My ADS-B feeder;
  5. My coding projects;
  6. My mechanical keyboard;
  7. My travel router project; and
  8. My music hobby.

Without further ado, let’s begin.

BGP and operating my own AS

Perhaps the most dramatic change for my AS is that ARIN finally issued me a /22 of IPv4 after being on the waiting list for two years. This allowed me to deploy my own IPv4 in four different locations:

  • Toronto, Canada;
  • Kansas City, Missouri, USA;
  • Fremont, California, USA; and
  • Amsterdam, Netherlands.

I’ve also repurposed my old ASN, AS200351, to demonstrate how new networks can announce routes to the Internet, as well as documenting how to join an Internet Exchange.

Connectivity-wise, AS54148 joined two new Internet exchanges:

  • AMS-IX, the Amsterdam Internet Exchange, which is one of the largest in the world. Special shoutout to AMS-IX’s Bright Networks Club, which gave small networks like mine a free 1 Gbps port, as well as Lionel Douglas at AMS-IX for making it happen.
  • NVIX, the North Virginia Internet Exchange.

Location-wise, I’ve added an IPv6-only node in Zürich, Switzerland to my anycast network. I also lost BGP on the Hong Kong node due to issues with the provider, which is unfortunate. Still, I have reasonable coverage in Asia with the Singapore and Tokyo nodes.

My homebrew CDN

My CDN has undergone some further location changes this year. The following nodes were added:

  • Seattle, Washington, United States;
  • Ashburn, Virginia, United States; and
  • a new “China-optimized” node in Tokyo, Japan.

I dropped the node in Bangalore, India due to provider issues. At this point, cheap servers don’t really seem to be worth the toll they inflict upon my sanity.

Perhaps the biggest change is that I decided that my CDN is good enough on its own and has a better track record than Cloudflare in terms of uptime, given the number of Cloudflare outages we’ve seen this year. For this reason, I’ve fully eliminated Cloudflare from all my domains.

I’ve also documented how to set up PowerDNS to pick the closest available server, which includes instructions for anycast deployment, as well as how to use Galera to ensure the control plane is highly available.

Speaking of PowerDNS, remember how I mentioned last year that it was annoying that I had to ensure MaxMind had the correct data, since PowerDNS insisted on looking up the server’s location from IP in the GeoLite2 database? Well, this year, I got sick of doing this and created my own pipeline with mmdb-editor to postprocess GeoLite2 databases downloaded from MaxMind to include the correct locations for my own servers. This ensured the location is always correct. As a bonus, I can also have geolocation for internal VPN IPs, since nothing stops me from putting private IPs into the database.

My home server

As documented, I’ve replaced the crappy RAM in my server with ECC RAM, which ensured that any memory corruption would be detected instead of creating mysterious failures. I am pleased to announce that I’ve not seen any errors with the RAM. Specifically:

# ras-mc-ctl --error-count
Label   CE  UE
DIMM_A2 0   0
DIMM_B1 0   0
DIMM_A2 0   0
DIMM_B1 0   0
DIMM_B2 0   0
DIMM_A1 0   0
DIMM_B2 0   0
DIMM_A1 0   0

However, I decided to wait until I had the energy before doing the same upgrade to my desktop. This has proved to be a mistake due to RAM prices going up, and I refuse to pay the current market price…

I’ve also replaced the case, going from some crappy 20-year-old case to the Antec 1200, which I wrote about here. The case has been holding up quite well and was definitely a worthy upgrade.

Unfortunately, one of the HDDs in the RAID 0 array I used for “unimportant data” in my server decided to give up the ghost, causing the entire array to be destroyed. This forced me to recreate the array with new drives as RAID 1 to avoid the annoyance of redownloading the data, which I used as an opportunity to document how to recreate the LVM cache setup.

Speaking of storage failures…

My ADS-B feeder

Earlier this year, I wrote about creating a multi-network ADS-B feeder to report planes flying nearby. Unfortunately, my ADS-B feeder ran on a Raspberry Pi, which suffered an SD card failure.

Since I didn’t want to reinstall Debian on the Raspberry Pi again, I instead opted to use my old Atomic Pi to handle the ADS-B dongle and run dump1090. The various feeders are now run directly on my server in a separate VM instead, reducing dependency on crappy storage on Pis.

Unfortunately, as it turned out, feeders provided by certain plane-tracking websites are ARM only, and both my server and the Atomic Pi are amd64 platforms. For this reason, I had to build x86 packages for Flightaware’s PiAware feeder, which proved annoying.

However, what’s beyond the pale was AirNavRadar, whose rbfeeder only ran on Raspberry Pis and required fake sensor data to be emulated. It doesn’t build elsewhere. A Docker image for it exists that purportedly works on amd64, but upon further inspection, the Dockerfile simply installed qemu-user-static and armhf packages using Debian’s multiarch feature to run it under emulation. Another reason why you should never trust Docker images. For this reason, they are no longer getting a feed from me.

However, it’s not all doom and gloom. I would like to shout out to FlightRadar24 and Planefinder for providing amd64 Debian packages that just work out of the box.

My coding projects

I’ve also written a bunch of code this year outside of work:

  1. I created TOTP.fyi, which is a code generator for the time-based one-time password (TOTP) algorithm, commonly used by authenticator apps like Google Authenticator. This is meant to help developers easily test TOTP in their apps, such as by passing in codes that were valid in the past or will be valid in the future, but are currently invalid. Hopefully, this encourages more websites to implement 2FA correctly. I am always so disappointed when banks insist on using text messages vulnerable to SIM swapping, instead of something like TOTP, which is better. The gold standard is still security keys though, and it’s disappointing that so few people support it.
  2. On that note, I also created a tiny Rust app that returns the current time, called qtime, which I plan to integrate into TOTP.fyi to warn users if their local clocks are out of sync and the generated TOTP codes are actually invalid. Maybe that integration will be done next year.
  3. I am also working on the new Looking Glass Indirect Display Driver (IDD), which enables Looking Glass to be used without the overhead of capturing the screen or a dummy HDMI or DisplayPort plug, as well as acting as a very nice way to interact with virtual machines without any GPUs. I am mostly focusing on implementing a UI to manage the driver inside the Windows virtual machine, rather than the driver itself.
  4. I’ve also implemented a version of the Mayan calendar, in a similar vein to my French Republican calendar. Next year, I’ll probably write some posts explaining how the Mayan calendar works.

Next year, I also plan to resurrect one of my high school projects, clean it up, and publish it properly on GitHub. I’ll not spoil the surprise for now.

My mechanical keyboard

On the keyboard front, I continue to suffer from various problems. My old Corsair K70 MK.2 keyboard with Cherry MX brown switches finally gave up the ghost, generating random keystrokes without any keys being touched.

I had to bring out the custom mechanical keyboard I built last year, which continued to suffer from the problems I complained about last year, except the weird key registering problem spread to even more keys. Thankfully, I was able to prevent keys from double registering most of the time by changing the debouncing algorithm in the firmware, which is an advantage of programmable firmware on keyboards.

Based on other users’ reports online, the problem appears to be quality control in Akko’s keyboard switches. It was a shame because I really enjoyed typing on the Akko Lavender Purple switches when they weren’t busy acting up.

As a result, I decided to get similar keyboard switches from a different vendor, and I eventually settled on the TTC Bluish White Silent tactile switches. They feel quite good to type on, although they are perhaps a bit too silent. Still, this allowed me to revert the debouncing hack in my keyboard firmware, although there’s nothing I can do about the backlight situation caused by the “south-facing” LEDs, since I believe side-printed keycaps look silly.

Fortunately, the de Quervain’s tenosynovitis hasn’t returned, and I am cautiously optimistic about the future of my keyboard.

My travel router project

My travel router ended up having issues connecting to various hotel WiFi due to portals and weird routing in the GL.iNet software. I think I’ll need to rebuild it on stock OpenWrt and set up my own policy-based routing rules instead of fighting GL.iNet’s “user-friendly” prescriptive defaults. I am sure it works perfectly for most users doing basic things, but I needed more control.

Unfortunately, due to recent events, I am not travelling as often now, and so I haven’t really had much motivation to fix the router.

My music hobby

And finally, my music hobby. As I mentioned last year, I was planning to learn to play Debussy’s La fille aux cheveux de lin (meaning “the girl with the flaxen hair”), which I finally managed to learn this year. I created this recording:

This didn’t really turn out as well as I had hoped, but honestly, I just haven’t really had the time to practice piano. I am not sure I’ll have to energy to learn another piece next year…

Conclusion

That’s about it for 2025. I am not sure what 2026 will bring, but I suppose we’ll find out.

If you like my content and would like to support me, you can do so via GitHub Sponsors, Ko-fi, or Stripe (CAD)—though of course, this is strictly optional.

Alternatively, you can also check out my referral links for services that I use. Most of them will pay me some sort of commission if you sign up with my link.