Using Cloudflare Workers to serve custom error pages

I’ve recently had to shut down some old platforms. This presented an interesting challenge, as I had some requirements:

  1. No ongoing server costs/maintenance
  2. Custom error messages depending on the domain, so the solution can be applied to multiple legacy platforms
  3. Work across wildcard subdomains, which are used to identify the tenant

I already manage DNS through Cloudflare, and after investigating their Workers a little bit, I found that they provide the perfect solution.

Read more →

Syncing multiple GBs from EFS to a remote S3 account

Whilst shutting down some old projects, I’m archiving all of their folders and storing them in S3 in case of an emergency.

I don’t have AWS credentials stored and set up on the EC2 instance, so I’m passing them through as variables to the script below.

As with the script to export tens of thousands of individual MySQL databases, you’ll want to edit the values at the top.

  • EFS_MOUNT_POINT is the full path to where the EFS drive is mounted
  • S3_BUCKET is your target S3 bucket
  • AWS_… self explanatory!
  • ARCHIVE_DIR is the full path to temporarily store the archives
  • LOG_FILE is the path to the log file for this sync action
  • DEPTH sets the depth before creating a new archive (see below)

The $DEPTH value lets you control when a new archive will be created. In my situation, I have a directory structure like:

Read more →

Exporting 10,000+ MySQL databases

I’m a big fan of single-tenant databases, one for each customer. With MySQL and InnoDB, a single server can scale to tens of thousands of individual databases.

As long as you’re deliberate with your schema design up front - here, I’m a big fan of explicit key/value tables that let you assign arbitrary metadata to objects that are more normalised - you buy yourself incredibly simple isolation by simply selecting the appropriate database once you’ve identified your tenant (using PHP’s select_db()). This means you no longer have to rely on scoping your queries if using something like Eloquent or another ORM, or much worse, making sure to scope it yourself when writing manual queries.

Read more →

One-time Lemon Squeezy payments with Laravel + Filament

I’ve just completed my first tiny product DoubleShot, a quick and easy way to create and share ‘before’ and ‘after’ photos to social media.

The final piece was to get payments working so that people could buy the app and get access.

It seems that the favoured way to do this is with Laravel Cashier - have the customer create an account first, then subscribe that User model to a subscription plan. But I couldn’t find any examples of achieving this with one-time payments. I don’t want my customers to have to create an account first and then buy access!

Read more →

MacOS notarisation with Electron

While working on Ghostmail, an Electron-based Maildir frontend I’ve built, I had to get the app ready for distribution on other people’s machines by code signing and notarising it.

I’m using Electron Forge to build the app, and I expected everything to work pretty much out of the box. However, I ran into an important, niche issue that should be highlighted.

I added the dotenv package to my development dependencies, initialised it at the top, and filled out my .env file with the relevant values, taking care to create an app-specific password for my account.

Read more →

How do you find the good stuff buried in the noise?

I read a lot so you don't have to

Every week: 5 links that are actually worth clicking. AI, software development and more.
Zero spam.