Recent Posts (all)

Trust local caddy certificates on macOS

Up to today, I’ve been bothered by having local https websites served by Caddy, whose certificates were not trusted by macOS. Today, I rectified it.

For macOS (and Safari) to trust what Caddy deploys locally, I had to:

A screenshot of a certificate open with Keychain Access

Then, all the local websites Caddy is serving will be trusted automatically.

Posted on 30 Jun 2024

A culture of brutal honesty

The New York Times on how the AI pin flopped

Insightful linked post from John Gruber on why the AI pin flopped. This bit stood out to me as particularly insightful:

It is the kiss of death for any endeavor, creative or technical, to have a culture where brutally honest internal criticism is not welcome, especially when it goes up the chain. In fact it needs to be the expectation, if you’re pursuing excellence.

Posted on 07 Jun 2024


I recently started using docker_isbg, a container bundling isbg and imapfilter to filter out spam from a remote IMAP server.

Getting started is relatively straightforward and relies mostly on a JSON configuration file such as

  "server": "",
  "username": "",
  "password": "Password",
  "isGmail": "no",                        //Optional; Default = no
  "spamSubject": "[SPAM?]",               //Optional;
  "report": "yes",                        //Optional; Default = no
  "spamLifetime": 30,                     //Optional;
  "folders": {
    "spam": "Spam",
    "ham": "ham",                         //Optional;
    "sent": "Sent",                       //Optional;
    "inbox": "INBOX"

After setting it up to run on a non-Gmail email host, however, I noticed the logs were complaining that isbg couldn’t find Gmail-specific folders. That meant that, somehow, my configuration was telling isbg that I was on a gmail host, even though the line"isGmail": "no" was in my config.

After some looking around, I saw the offending piece of code in docker_isbg (newlines added for clarity):

if( confLoader.tableHasKey( config, "isGmail" ) 
    and config.isGmail ) 
      gmailOption = " --gmail" 
      gmailOption = "" end 

The code checks whether config (which is a dictionary-like object resulting from the parsing of the above JSON) has a isGmail key, and whether it is set to anything: it can be yes, no or any other string and it will pass the --gmail option to isbg.

To fix it, I opened a PR that changes the above lines to

if( confLoader.tableHasKey( config, "isGmail" ) 
    and config.isGmail == "yes" ) 
      gmailOption = " --gmail" 
      gmailOption = "" end 

While the project seems to be mostly abandoned so I don’t expect a prompt merge, there’s another easy fix: changing the "isGmail": "no", line to "isGmail": false in the configuration file as in that case the config.isGmail code will evaluate to false.

Posted on 05 Apr 2024

Start using ddclient

For more than 10 years, I’ve been a happy client of Tweak (how long will that link work?). One of the many features it offered was a fixed IP address.

Now that I’m forced to switch to Odido, I will lose this affordance, which serves me greatly whenever I need to connect to my VPN at home. In fact, my phone and laptop are configured to just connect to a subdomain of, which pointed to my home address, and that address never changed.

I then started looking for ways to update my IP address automatically. Luckily, there seems to be a service that’s been designed for this, ddclient that I’ve set up in my home server as follows:

# ddclient.conf
    container_name: ddclient
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - /path/to/code/ddclient:/config
    restart: unless-stopped
[migrations] no migrations found
usermod: no changes
      ██╗     ███████╗██╗ ██████╗
      ██║     ██╔════╝██║██╔═══██╗
      ██║     ███████╗██║██║   ██║
      ██║     ╚════██║██║██║   ██║
      ╚══════╝╚══════╝╚═╝ ╚═════╝
   Brought to you by
To support LSIO projects visit:
User UID:    1000
User GID:    1000
[custom-init] No custom files found, skipping...
Setting up watches.
Watches established.
[] done.
/config/ddclient.conf MODIFY 
ddclient has been restarted
Setting up watches.
Watches established.
SUCCESS:  updating ipv4: skipped: address was already set to ...

That’s it. Just a few lines of code, and the problem is gone!

Posted on 26 Mar 2024

Bitten by timezones and Docker

I am building a Telegram chatbot to remind me to take out the trash.

I’m overengineering it, so of course it has Docker and a (sqlite) database.

One component of the chatbot does an hourly check. If tomorrow the trash will be collected, and the current time is later than the time I want to receive the notification (and if I haven’t been notified today), I should get a message.

However, I was not getting the messages. The code seemed solid

  TIME('now', 'localtime') > TIME(time_of_day) AND
  DATETIME('now', 'localtime', '-1 day') >= 
  DATETIME(last_executed_run, TIME(time_of_day))
  last_executed_run IS NULL

Worse of all, when I was running on the Docker host, I would get notified at the right time.

It turns out Docker doesn’t respect the host timezone, but you need to be explicit about it, adding a TZ environment variable (in my case TZ=Europe/Amsterdam).

Posted on 15 Mar 2024

Automatically add images for Open Graph in Hugo

While using a static site generator is a low-maintenance endeavor, it also means that complex requirements need to be coded if nobody has done it before. Today, I automated image previews that can be used to display a nice preview through for Open Graph (and Twitter cards!).

The Open Graph protocol enables any web page to become a rich object in a social graph. My blog, however, is text-heavy and often misses the images, so I had to come up with something else.

In the end, I settled with a solution (code below) that displays a static image with some text on top, including the title, a snippet of the blog, and the URL.

The snippet can be explicitly set in the front matter with the snippet key, otherwise it will take the first characters of the post itself.

To make it all work, you need a couple of things in your Hugo theme

├── assets
│  ├── Inter-Medium.ttf
│  ├── Inter-SemiBold.ttf
│  └── og_base.png
├── layouts
│  ├── partials
│  │  ├── opengraph.html

Here, og_base.png is just the empty image used to write text on, like:

The open graph base image

The fonts are just the fonds, and opengraph.html contains:

In the, then, every blog post will be accompanied by an image as

The rendered open graph image
Posted on 14 Mar 2024

Men Children

An interview with Lyz Lenz

In the quoted toot, Lyz Lenz offers the wrong solution to a wide-spread societal problem: men who have remained children.

Our society tries to delay or prevent people growing up: making irreversible decisions, taking responsibility, caring for someone else more than for yourself, suffering.

Women are forced to much of the above when they become mothers (an irreversible decision, they take responsibility for the newborn, they will defend their child with their life, and laboring is a lot of suffering).

Men, on the other hand, can skip everything when they become fathers: they can leave and, when they stay, they can pretend to continue as nothing happened.

The tragedy is a that the situation creates a vicious cycle: as the father is absent or doesn’t take up his duties as a father, the mother protects her child even more, making it hard for the child to grow.

Posted on 23 Feb 2024

Public Appearances

I’ve added a page about my public appearances throughout the years. I still have to figure out how to make it load faster with all those pesky videos coming from youtube!

Posted on 15 Feb 2024

China's Economy

Has Xi Jinping lost control of the markets?

What’s happening in China is really interesting. If we trust their official figures and estimates, the economy was driven by 3 things:

  1. Real estate (who’s crashing hard)
  2. Consumer spending (who’s in decline, as their population is not growing and aging)
  3. Exports (who are threatened by India and South East Asia)

As 1. is crashing, consumers—who put most of their savings in, guess what, real estate—are more conscious about spending, hurting another good 30% of their economy.

So, 2/3 of their economy is hurting and will hurt more badly in 2024.

The Chinese’s and Hong Kong’s markets are also spooked, having shed USD 1.5 TRN in January alone.

It’s going to be an interesting 2024.

Posted on 09 Feb 2024

Decode your URLs

Today, I read Terence Eden’s article about the abundance of Microsoft’s safelinks systems. One example he gives is

As my work email is hosted by Microsoft, I’m bugged to no end by this system, which doesn’t make it easy to extract the URL in a readable format (read the blog if you want to know more shortcomings of the system).

For a couple of years, I have a Typinator snippet that decodes the URL, so that by typing ;dec, the following script is triggered

let URI = "{clip}".split("=", 2)[1].replace("&data", "")
let encURI = decodeURIComponent(URI)


Converting the above link to

The script is not perfect, but, since defining it, Typinator analytics tell me I’ve used it some hundred times and I can’t recall when it didn’t just work.

Posted on 06 Feb 2024