tzeejay icon




The Missing Workhorse Mac

The Missing Workhorse Mac

Processing intensive workflows are higher in demand than ever, but the Mac lineup is missing a crucial piece to help pro customers of Apple.

AVM Fritz WiFi Mesh

AVM Fritz WiFi Mesh

AVM Fritz WiFi Mesh kam unerwartet ist aber ein Segen für den deutschen Markt

Turning iOS Extensibility to 11

Turning iOS Extensibility to 11

iOS is amazing but is lacking productivity basics

WWDC 2022

If you have been following me on Twitter for a little longer you are aware that I am quite outspoken about things like App Store policies, Apple’s seemingly great service revenue and their interaction and treatment of developers. If things right they should be praised and if things are wrong they should be critiqued. Nothing good is created or can exist in a vacuum without feedback.

Over the past 3 years relations between developers and Apple have gone from indifferent at best to outright hostile. WWDC always moves the general sentiment to being more favorable and friendly, this year however has built on top of the very good remote WWDC we got to enjoy last year. I have not participated in digital lounges or other events due to various reasons but have heard from many that they have really enjoyed it.
With various people that I know of, listen to Podcasts to or know personally being in person at WWDC in Cupertino has really made me wish to be able to be there as well. It filled me with an enormous amount of envy. Envy to be there and experience the energy in the “room”, envy to make new friends, envy to share ideas, envy to learn & envy to see my friends.

The cool kids got to fly to Cupertino. I wish I was part of the group of cool kids.

Thank you Apple for a great WWDC 2022. It feels like you have figured out what you want this to be going forward and I am excited to keep being involved in developing software for these platforms.


Check PostgreSQL TLS Certificates in Pure Go

TLS certificate expirations are quite embarrassing but still happen somewhat regularly to various services of all sizes. The core system at Guardian Firewall that I maintain have had such outages as well and I was just as embarrassed. The second was not my fault but rather a bug in an automated tool that we use to obtain a Let’s Encrypt certificate for our servers, still though these are things that I should have caught and should not have happened. Not my fault does not mean not my problem.

To prevent these scenarios I built a system that checks a manually defined list of servers once every 24 hours and alarms us in a special Slack channel if the expiration date for the server has crossed a certain threshold. If the threshold dips below 7 days it even @ mentions a group of people which leads to a push notification on all logged in devices for all members of the group. Somebody responsible will be hearing about this problem.

Doing this to HTTP connections in Go is straightforward as everything is very openly exposed by the Go stdlib but we also run PostgreSQL as our core database engine and we wanted to make sure to include it in these routine checks as well. Connections to the DB never hit the public internet in my setup or are always properly encrypted through a local port forward of a SSH session, but sprinkling some TLS 1.3 on top shouldn’t hurt anybody. Having a valid & trusted certificate is easy to come by these days and will remove some friction while using the system.
It’s free real estate operational insurance.
When I initially built this system I was struggling to understand how the TLS connection to PostgreSQL is established as tls.Dial("tcp", "postgres-ip:5432", &tls.Config{}) will try to do the right thing but ultimately fails and leads to an obscure error in the PostgreSQL log:

2022-06-07 12:25:38.754 UTC [7325] [unknown]@[unknown] LOG: invalid length of startup packet

That right there should have been enough of a hint for me to figure this out, as I am a little familiar at the very least with STARTTLS from my adventures into running-your-own-email-server land. The connection is initiated unencrypted, you pass a (not so) secret “phrase” to it, it responds with a (not so) secret “phrase” back and you can finally upgrade the connection to being encrypted by initiating the TLS handshake.
It is very easy to type out in hindsight as this all makes sense to me now, but I was really struggling to wrap my head around it not even 24 hours ago.
Thankfully though I have amazing colleagues, who are quite a bit smarter than me. This explanation made me understand the process immediately and I hope that it will help somebody else as well.

15:14 Uhr
It's a custom protocol.
15:15 Uhr
So you want to send this 00 00 00 08 04 D2 16 2F.
15:16 Uhr
Read the first byte.
15:17 Uhr
It should be character S.
15:17 Uhr
Then write/read the SSL handshake start.
15:18 Uhr
The TLS session only starts after that first byte.
15:19 Uhr
So a normal TLS socket will fail because it will receive that first byte which doesn't really make any sense because it's part of the binary PG protocol.
15:21 Uhr
openssl s_client -starttls postgres basically does that, it sends the PG magic to start the TLS connection.
15:21 Uhr
You can't do it the "normal" way.

The protocol as published by the PostreSQL authors can be found here.

She graciously published her little POC Golang program for me so that I can include it on here as well.

Mirror in case Github does something stupid

Building these little early warning systems yourself is not difficult and I would encourage anybody to do so. Save yourself from the “embarrassment” of having your TLS certificate expire in the year 2022 and beyond by having a little computer give you a nudge every once in a while.

If you find yourself struggling as I did with this task I hope this post helps you.


Monodraw Licenses Giveaway

It may come as a surprise to some, but I am doing something good just because I can and it will make me happy to see other people happy.

A little while ago the developer of the wonderful iOS Reddit client Apollo Christian Selig and I had a public exchange on Twitter about ASCII art in one of Apple’s new OSS projects. To my surprise this caught the attention of a few people. Christian & I talked about how fun it would be to launch a little giveaway, not to gain followers or sell anybody anything. Do something fun on the internet with strangers after two absolutely awful years just because I can. I ended up doing exactly that and got into contact with the Monodraw developer hoping I could purchase the licenses in bulk but ended up with ten free ones to give away.

How To Enter The Giveaway

I have decided that I will give away the licenses at random to people on Twitter leading up to Christmas. I don’t care if you follow me or not and it’s not a requirement, I just want to hear what you’re up to or what you’d like to use Monodraw for. There are bonus points if you are a student and if it would help you with class work or in a paper that you have to write, but that is also not a requirement. To enter simply mention @tzeejay on Twitter or send me an E-Mail. I prefer Twitter as I want to publicly share what you’re up to but it’s not a requirement.
If I think you’re doing something cool I will send you one of the licenses. No strings attached!

(If you think the app is cool and end up missing out on the giveaway, just treat yourself to a license. It’s only $10 and well worth the money)

Terms (?)

I was generously given the ten licenses, two of which I will give away every Advent, the first one being tomorrow 2021-11-28, and the remaining ones on Christmas (that is the 24th for y’all Americans).

Whatever holidays or festivities you observe during this time of the year, I hope you catch a break and have some free time to have some fun drawing some ASCII art. We all deserve it.


Boring Tech: No-Touch Foamy Soap Dispenser

You can file this under “2021 hitting hard, man”.

The day has come that I am publishing something on my website not just about soap, but a soap dispenser. To be very honest with you though, this was a purchase initiated by my girlfriend that I am really enjoying.
I am usually the type of person that likes and defends mechanical systems of any kind as way too many things in our lives are either electric now for absolutely no reason, or even worse want to be connected to the internet at all times (to collect & sell data about you). I have now been working from home for many years and very regularly wash my hands, even pre-covid hand-washing hype, and therefore made heavy use of our previous soap dispensers which can be described as “fine”. They were nothing I would write a blog post about but they also did nothing wrong.

This dispenser is something else though. The packaging is not very reassuring at all, as it comes in a plain white cardboard box barely big enough to keep the dispenser inside, but the way this thing operates is very satisfying.

  1. It reacts very quickly
  2. I have never had to wiggle my hand underneath the sensor/nozzle to make it recognize that I am trying to use some soap
  3. The dispenser moves the soap very quickly. I would say that it isn’t slower than taking one to two pumps with a manual soap dispenser.

Getting these basic feature so right totally won me over and we now have two. The battery came pre charged in both and the package includes a little USB-A to USB-C cable to charge it through the rubber sealed USB-C port at the back. Neither had to be recharged since we got them and neither the soap extrusion speed or any other indicator that it might be low(-er) on battery has decreased so far.

I would assume that you can buy suitable watery soap in bulk refill packs but as per their instructions, watering down liquid soap with the viscosity similar to honey works too. They recommend a 2:1 water to soap ration but I’d recommend using more like 3:2. It’s soap, it doesn’t need to be an accurate science.

I am sure that the same dispenser is sold around the world under different nameless brands but here are & links.

Edit 2022-01-15:
I have been a little depressed to write this update as I really like this stupid soap dispenser. They’re cheap garbage and break almost instantly. We’ve now purchased three of them with one working perfectly to this day, one arrived broken and the third broke after one week of usage. On the inside they’re nothing but a little PCB at the top, a 18650 battery cell and a little DC motor + pump. There are no fancy parts in here though it appears as if there is not a single reliable manufacturer for these simple devices. It is all just cheap Chinese shit and it really angers me. I wasn’t even able to bring myself to send the last one back, as I know that it will end up in a landfill. I rather cut it open too and harvest the little motor & 18650 battery cell. Maybe I can use them in some project in the future.


Making Your Mac App Launch on Login (An iOS Developers Opinion)

I have been a Mac user for quite a while now and while I understand how some underlying technologies work because I had played with them in the past, actually writing your own Mac app gives you an entirely different point of view. Today I had quite the “you have got to be fucking with me” moment.

I have tried to make Guardian Firewall for Mac, which is still in beta, launch on login/boot. The solutions I have found kept getting worse and worse and user interaction in any way seemed to not be required at all. Coming from iOS with it’s very locked down OS and requiring external user input for basically anything at this point because some developers just have to be terrible and abuse every little bit of API platform, I just couldn’t believe the state of the Mac at the moment when the solution to this problem is seemingly so obvious.

There are many ways to add launch items on Mac but the “oldest” way to accomplish this that I know of is by dropping a .plist file into ~/Library/LaunchAgents/ (or /Library/LaunchAgents for all users of the Mac). You define a few keys and values in the file and move on with your life. There are also other ways to do this but this variant is quite easy to explain and very flexible as it is just a plaintext file.

To me, the way to actually solve this problem from an app POV interacting with APIs would be to call a NSApplication method with a completion handler, similarly to how you ask for permissions on iOS or macOS to access location data. This way both sandboxed and non sandboxed apps can easily adopt this new API and the user is presented with a little modal alert containing a short explanation by the developer asking them for confirmation. Behind the scenes macOS creates a .plist file with a reference to the app and the drops it into ~/Library/LaunchAgents/.

This solution would offer a few key advantages:

  1. It guarantees backwards compatibility & existing apps will continue to function
  2. With the correct permissions (or by being root) a script or any sort of automation tool can still accomplish the same task
  3. All Mac developers get access to a supported & predictable API in an already established format
  4. Compatible with sandboxed or non sandboxed apps
  5. Going forward the user will have a clear expectation about the interaction
  6. API adoption can be enforced for sandboxed apps (I would absolutely endorse the app review enforcement in this case)

The current possibilities as for example described here, which include a little helper app that has no UI but is yet another target that needs to be included in the bundle and codesigned properly sound like nobody has had the chance to give all of this enough thought. Especially given the changes Apple has made over time to the Mac sandbox.
Making this change would make the Mac a more secure platform without limiting power users in any way.


Support E-Mails are Fixed in iOS 15

Back in March I wrote about how an update to iOS 14 had completely turned our very simple support inquiry strategy onto its head and I wrote about my frustrations while trying to adopt the, old at this point, iOS share sheet. It is still completely broken and impossible to pass along any kind of formatted text into certain fields in a predictable way. As far as I was able to follow the breadcrumbs with iOS 15.0.1 or iOS 15.0.2 Apple at least fixed the mailto:// links they had broken in iOS 14.6 to address a 0-day (I am failing to find the links now but here is the Security Update Disclosure).

In order to send details about the state of our app we allow customers to opt into sharing details via simple UISwitch-es. We receive data in a somewhat predictable format as well as a written message with context about the problem and our customers have the ability to verify and edit which details are being shared with us.

Guardian Contact Technical Support UI Guardian Contact Technical Support Formatted E-Mail

Our goal is to make things as convenient as possible for them to share crucial information with us to help them, but not beat them over the head with it by forcing anybody to share something they don’t feel confident in sharing. We prefer having to ask for more details over collecting any data automatically without the users input or explicit acknowledgement. Discipline and restraint will win you long-term trust in this situation and it is always worth it in my opinion.

To give a concrete example, this is what a support inquiry formatted on iOS 14.8 looks like:

<BR><BR>Please describe in detail the issue you are experiencing <BR><BR>###<BR><BR>VPN Hostname<BR>sanjose-ipsec-4<BR><BR>Subscription Type<BR>Quarterly<BR><BR>AppStore Receipt<BR><BR><BR>App Version<BR>2.2.4 (4)<BR><BR>iOS Version<BR>14.7.1<BR><BR>iOS Timezone<BR>America/Los_Angeles<BR><BR>Network Type<BR>WiFi<BR><BR>Cellular Carrier<BR>REDACTED<BR><BR>Subscriber Credential<BR>REDACTED<BR><BR>Issue<BR>App doesn't work (Not Guardian)

I think it is obvious to anybody why receiving such messages would suck. Yes we could setup triggers or webhooks to clean this up and simply replace all instances of <BR> with \n but we shouldn’t have to do that in the first place.

Thanks to iOS 15 being such a solid update and the great adoption rate we are seeing, these E-Mails are less and less common. Instead we are now receiving support inquiry E-Mails looking like this:


Please describe in detail the issue you are experiencing 


VPN Hostname

Subscription Type

AppStore Receipt
No App Receipt Available

App Version
2.2.6 (20211103.5)

iOS Version

iOS Timezone

Network Type

Cellular Carrier

Subscriber Credential

Exceptions Log

App doesn't work (Not Guardian)

Critical details like the app version are glanceable again reducing the support overhead significantly. Looking for details in an ocean of <BR> once is easy. Do that all day and you will quickly look for alternatives.

I hope that we are able to inspire more developers to adopt this kind of support ticket system as plain-text will work with any regular E-Mail account as well as more fancy systems like Zendesks and the like.