The end of Airport
It’s been coming for a long time. Since 2018 when Apple discontinued the Airport routers its been a ticking time bomb till it all would end for real. The hardware was excellent and I used all of it, the software was the ultimate Apple, simple and it just worked. I’ve had several types of Time Capsules which I used as a router and for Time machine backups and a plethora of Airport Express. I think I’ve had all the models, from the plug model to the Apple TV like puck. It was simple and elegant, in software but also the hardware. You could leave the white devices anywhere without becoming an eyesore.
As the writing was on the wall and the need to stay compatible with all the new hardware devices using later Wifi standards I switched to Ubiquity just more then a year ago. It was and still is the most Apple like experience when it comes to networking, even the unboxing experience is nearing Apple like standards. The software is a bit more complex as it also targets enterprises but for simple home use you don’t need to invest into learning all the networking details most of it works out of the box. The hardware also looks good, for my access points I had chosen the U6 Mesh as it had for me the best looks. It does not resemble a regular networking device and doesn’t gather attention.
As I still used an old Time Capsule, integrated in the Ubiquity network for my Time machine backups we started getting the warnings that from macOS 27 Golden Gate this wouldn’t work anymore. So when Ubiquity released their Unas 4 I waited to see how the reactions and real world experiences worked out. While there are some downsides for heavy usage it was sufficient for my requirements. I don’t need a NAS which can run all kinds of software, I just need storage. So I pulled the trigger a few weeks back when I got notice that they were back in stock (somehow it looks like they are popular). I’ve scrounged every spare hard drive I could find to fill it up as the current AI craze has increased the price for drives and ram to crazy hights. I even salvaged the drive from my Time Capsule to extend is use in the UNAS 4. So it’s not ideal, different sized hard drives, not really using RAID, but untill prices come down it works for me.
This al meant I was no longer using any of the Apple Airport, and when I read a few weeks back that someone had extended the life of the Time Capsule problem by installing Samba on it I almost felt sorry for replacing it. But the news this week finally put the nail in the coffin for Airport. As MacRumors unveiled, Apple Dropping AirPort Utility From the App Store With iOS 27, you wouldn’t be able to configure or access the settings anymore. Which basically would mean the end. Apple has done a great thing by supporting it this long.
I’ve loved all my Airports and was sad when they were dicontinued, I’ve tried hanging on as long as possible. There is still some hope that Apple will get back into networking but I don’t think that will happen, same with printers.
Account deletion @ bkmrkd.it
I’ve been struggling with the account deletion feature at bkmrkd.it. Specifically if users have large amounts of bookmarks. The Lambda proces time limit make it a bit trickier than just a normal program. You have to limit the amount of CPU per call. So the simple method first tried was to paginate (like browsing through your bookmarks) thourg the list of bookmarks and deleting them in batches using SQS for triggering each batch. This triggered another “hidden” feature I didn’t know about while testing this: Recursive loop detection and auto remediation.
At first I thought I missed something in my code as the deletion process didn’t finish as expected but stopped halfway. It all became clear the next day when I received an email notification from AWS:
Hello,
AWS Lambda has detected that one or more Lambda functions in your AWS Account: ########## are being invoked in a recursive loop with other AWS resources. To prevent unexpected charges from being billed to your AWS account, Lambda has stopped the recursive invocations listed in the ‘Affected resources’ tab of your AWS Health Dashboard.
This scared me at first but my trusty AI companion walked me though some of the options. The difficulty being that unlike relational databases there is no possibility do a “DELETE FROM TABLE WHERE COLUM = X”, you have to do a scan or query and then iterate trough the result set which is in itself timeconsuming on large datasets. As I stored 2 records for each bookmark, one for quick lookup and finding and one with all the details this made it increasingly difficult. So I did a rethink on the datamodel, which resulted in a single record per bookmark.
The records now all have the same PK which makes deleting everything from the same account easier. Another design choice was to move the bulk deletion out of Lambda and proces it locally. I now only delete the account details directly and leave the bulk deletion for a later moment outside of Lamdba.
By the way, the export functionality was quite the opposite and easy without significant problems. It is basically the same idea because of the time limit. I chunk through all the bookmarks, outside the main program and build a set of JSON files which I zip together at the end and send an email with a download link. Works like a charm.
Fred again.. & Thomas Bangalter
First thing I thought when reading about this was: Tomas who? Then when reading and listening I recognised it, Thomas Bangalter was one of the illustrious duo Daft Punk. I didn’t recognize him witouth the helmet. This video has been on repeat for several days now, it’s a banger. Fred again.. with Daft Punk doing a 2 hour long DJ set. What can I say, it’s epic. Listen and enjoy!
Restarting bkmrkd.it
It is finally in a state that is usable and presentable, I’ve been working on and off in my spare time since the end of summer last year. I wanted to learn and experience the benefits of using a serverless platform. The simplest way to start that journey was with Chalice, a ready made framework to develop for AWS Lambda.
The project that I’ve wanted to reboot was my bookmarking website bkmrkd.it which I developed some time ago using the PHP Laravel framework but never quite finished it. It was usable for me but I never completed user registration and other features that were still on the todo list.
The current release is working, but not completely finished or polished. All the information is there and the basics work, you can register and add, edit and delete bookmarks with tags. It is even possible to import bookmark files from your browser to give you a head start. There might be some minor bugs, I’m still testing and debugging but it is good enough to release it publicly.
Still to do:
- export functionality (will time out because of the time limit for lambda functions, need to implement a background process for this)
- deleting user accounts (same problem, time limit if you have a large amount of bookmarks)
Dropping Multipass for OrbStack
I’ve had it with Multipass, again after upgrading to a newer version of OSX (Tahoe in this instance) Multipass isn’t starting up again with the dreaded “can’t connect to socket” message. I could not resolve it, even restarting daemon and re-installing didn’t resolve the issue. Whilst next to it I had OrbStack running with an X86 ubuntu VM and a local-stack docker image for my Chalice project which was still running as expected.
This made me rethink Multipass, after some thinking and a small experiment I decided to drop Multipass completely and switch all my VM projects over to OrbStack, which was easier then expected as it also supports cloud-init which I was already using for creating VM’s. The only change was needed to my setup scripts in ‘bash’ as the command line for OrbStack is different.
The command line for OrbStack has some peculiarities which I will document here as I had to discover them by trial and error and digging through forums, etc…
Orb will create a user in your VM which is identical to your Mac username. So to use the regular ubuntu user as you main user you have to specify this when you create your VM.
orb create -a $ARCG -c $CLOUDINIT.yaml -u $USERNAME ubuntu:$VERSION $VMNAME
where
- $ARCH is either arm64 (for native Mx) or amd64 (for X86 compatible VM’s)
- $CLOUDINIT is your cloudinit configfile
- $USERNAME is the primary username to be installed on this VM, likely
ubuntu - $VERSION is the version of Ubunu to install but is optional, if left out the latest version will be installed
- $VMNAME is the name of your VM, will be accessible as $VMNAME.orb.local on your network.
It is not possible to set the amount of CPU, Memory or disk space per VN. You can only set the maximum amount of memory and cpu for the complete OrbStack environment.
Copying files to and from the VM is simple, using orb push or orb pull commands:
orb push -m $VMNAME source destination
Executing commands is simple but has some intricacies as where they are executed is not always clearcut, especially if your command is longer and uses piping for instance. You might end up piping the output of a command on your VM to a file on your Mac. For instance: orb -m $VMNAME sudo service mysql restart is pretty straightforward but:
orb -m $VMNAME mysql -uroot -psecret dbname < /home/ubuntu/projects/outfile.sql'
will let you know that the file isn’t found. To solve this you have to use quotes and the -s option
orb -s -m $VMNAME 'mysql -uroot -psecret dbname < /home/ubuntu/projects/outfile.sql'
Something I havent solved yet is that using cloud-init to set hostname or FQDN does not work yet.
I’m abandoning my multipasssetup project as I won’t be using it anymore. I will create something similar for OrbStack.
Embrace boredom
This video really hit me, which I noticed via Kottke. I really try to take time out to be bored but there was no real drive or meaning behind it. For instance I only work 4 days of the week, because I need time to unwind but also need time to process and order everything I’ve encountered.
Arthur Brooks really brings his point across with some good examples but also has some excellent suggestions on how to get and stay bored!
Chalice development and deployments
I’ve been playing with AWS Chalice and rebuilding a bookmarking web app I had earlier witten in PHP Laravel. I wanted to learn serverless development and this looked liked the simplest route to get started using a known language Python. I also thrown in some LLM support, by using the free version of ChatGPT, as an assistent in learning the new environment.
Developing and running it locally was easy, there is a docker image available for having your own DynamoDB for a backend database and a simple install of Chalice. The hard part was when development was finished to get it running on the actual AWS infrastructure. It all looked fairly easy but then the errors start appearing. I’m documenting my findings here so others will find the working solution easier then I did.
First error I ran into is that because I develop on an M1 Mac, everything was based on the ARM architecture, and there is no feature yet in Chalice to deploy to the ARM AWS infra. It just defaults everything to the X86 infrasturcure. There is a feature request to handle this but it looks like development on Chalice has slowed down. Quick thinking was that my Mac supports X86 with Rosetta2 and I would just need to spin up an X86 Ubuntu VM to build the Chalice package. Next issue, Multipass does not support this yet. Luckily I found OrbStack where the architecture of your VM is selectable, downside is you can’t set the amount of CPU or memory per VM. It does support cloud-init, just like Multipass so my setup scripts are re-usable.
Second error, permissioning. Chalice, by default, creates the roles it needs to execute the lambda functions. However it leaves out the access rights for the DynamoDB table I needed. ChatGPT went off the rails here by proposing several different suggestions, which followed after I responded that the solution didn’t work. First I had to include a policy.json in the root of the project, next solution was to include the policy in the config.json which also didn’t work. A classic search showed me this and this article which showed me how it is done. First in your config.json add "autogen_policy": false in the required stage and then create a policy-stage.json with the details in the .chalice directory. Later I found the official documentation which described the same solution.
A related problem was using different AWS Access Keys for each stage of development, so using different identities for dev, acceptance and production. Again ChatGPT gave different answers depending on the question but eventually found a solution that worked. You store your credentials in ~/.aws where you have two files: config for your region and credentials for your acces and secret key combo’s. For the credentials it is straightforward just use [stage] to define the applicable stage but for config it is different and you should use [profile stage]. See the following example for credentials:
[default]
aws_access_key_id = yourkey
aws_secret_access_key = yoursecret
[acceptance]
aws_access_key_id = yourkey
aws_secret_access_key = yoursecret
and this for config:
[default]
region = eu-west-1
[profile acceptance]
region = eu-west-1
Third and last error, packaging static files. As I’m using jinja templates to create the webpages in Python, they need to be included in the packaging for deployment. Again ChatGPT gave non-working solutions and the web had no definite answer as well. Some indicate using the vendor directory where you can store specific non standard python packages, other specify using the chalicelib directory .
The official documentation is not quite clear on the route. I’m currently using the vendor route but will try the chalicelib option as well.
Privacy and independence
A blog post by Lukas Mathis has been sitting open in my browser tab for almost two weeks now. Every time I see it, it reinforces something I’ve believed for years: our growing dependence on big tech services comes with hidden costs that many of us don’t fully consider. Lukas’s post strikes a chord with me on multiple levels, and I think it’s worth exploring why digital independence matters more than ever.
The most obvious concern is privacy. When you upload your photos to Google Photos, your documents to Google Drive, or your files to any cloud service, you’re essentially handing over control of your personal data. Sure, these companies have privacy policies, but those policies can change. And even with the best intentions, your data becomes subject to their business models, government requests, and potential security breaches. Lukas uses photos as his primary example, but the issue extends far beyond image storage. Your emails, documents, notes, contacts, calendars—essentially your entire digital life—can end up in the hands of companies whose primary allegiance is to their shareholders, not to you.
The second issue that resonates with me is dependency. Cloud services can disappear overnight. Companies can change their terms of service, increase prices dramatically, or simply decide you’re no longer welcome on their platform—all without meaningful recourse for users. I’ve seen this happen repeatedly. Google alone has a graveyard of discontinued services that once hosted people’s important data. When you’re dependent on a single provider, you’re essentially betting your digital life on their continued goodwill and business success.
This is why I’ve made deliberate choices to maintain my digital independence, even when it means sacrificing some convenience.
I gravitate toward Apple’s ecosystem not just for the user experience, but because their business model doesn’t depend on harvesting my personal data. I also deliberately limit my social media usage—partly for mental health reasons, but also to reduce my digital footprint. For photos, I’ve skipped iCloud Photos entirely. Instead, I store my photo library on a local NAS (Network Attached Storage) device, which I then back up to the cloud using strong encryption. This gives me the best of both worlds: local control over my data with the safety net of remote backup.
One of my longest-running projects has been hosting my own email server—something I started doing over 20 years ago. Back then, it meant manually compiling and configuring everything from scratch, spending countless hours debugging mail server configurations and fighting spam filters. Today, I use Mail-in-a-Box, which has transformed email self-hosting from a masochistic technical exercise into something remarkably straightforward. The software handles all the complex configuration automatically while still giving me complete control over my email infrastructure.
The beauty of this approach extends beyond just privacy. Because I control the entire stack, I can host it with any VPS provider I choose. If I’m unhappy with my current host’s service, pricing, or policies, I can simply spin up a new server elsewhere and restore from backup. This portability is freedom in the truest sense.
If you’re interested in taking back control of your digital life, you’re not alone. The self-hosting community has grown tremendously, and the barrier to entry has never been lower. Lukas mentions the awesome-selfhosted GitHub repository, which is an incredible resource. This curated list contains hundreds of open-source applications that can replace virtually any cloud service you’re currently using. Whether you need file storage, media streaming, password management, or collaborative tools, there’s likely a self-hosted solution available.
I won’t pretend that digital independence comes without costs. Self-hosting requires time, some technical knowledge, and ongoing maintenance. You become responsible for updates, security, and troubleshooting. The convenience of “it just works” that comes with major cloud services is genuinely valuable. But for me, the trade-offs are worth it. The peace of mind that comes from knowing I control my data, that I’m not subject to arbitrary policy changes, and that I can switch providers without losing years of digital history—that’s invaluable.
Some small updates
Last weekend I updated my Mail-in-aB-ox server because my old server was still running Ubuntu 18 and the current version requires Ubuntu 22.04. I was several versions behind because I dreaded the upgrade process. In the end it almost went smoothly, I had some struggles with restoring my data but that was caused by my inexperience. I’m stil in awe of how simple it has been made.
By re-installing my box I also had to go through my own instructions of running AWStats for the static websites that are hosted on the mailserver. I noticed som small inconsistencies and made some steps a bit clearer on what to do.
The other change I made is the addition of another configuration file in my multipass setup scripts. I’ve been playing with AWS Chalice. It’s a framework on top of AWS Lambda functions and DynamoDB. The installation includes a docker image of a local DynamoDB server to use for local development. The file is called chalicedev.yaml. Have fun.
Multipass update, using config file
I’ve been quite busy at my regular job sand didn’t have the time for personal projects or blogging, sorry for that. As you might remember from earlier posts that I don’t like to develop on my machine itself, I like to create purpose build virtual machines to develop specific projects. This helps me separate requirements and conflicting libraries and versions of software which might break projects. I use Multipass as the virtualisation tool for managing virtual development machines on my Mac Studio using cloud-init for automation.
Up until now I was happy using just one configuration file for each VM as my personal projects didn’t differ that much from programming tools perspective. At my latest project I found out that they will and I needed an option to create different configurations per VM. So I’ve added a command line option to make the configuration of the VM flexible. It’s the YAML file that cloud-init uses to install all the required packages and set the proper configuration items.
It required me to adjust the documentation and to update the remote multipasssetup repository on BitBucket. I quickly ran into issues with Git as I had made a correction, resolved a typo, remotely without merging so my local and the remote repo where out of sync. Took some effort to getting it resolved as I’m no git expert ;-).