<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://chameth.com/">
    <title>Chameth.com - posts like android-espresso-spoon, how-i-get-things-done, tailscale-docker-gotcha but not docker-automatic-nginx-proxy, why-you-should-be-using-https</title>
    <subtitle>Personal homepage of Chris Smith</subtitle>
    <link href="https://chameth.com/feeds/posts/like/android-espresso-spoon,how-i-get-things-done,tailscale-docker-gotcha/unlike/docker-automatic-nginx-proxy,why-you-should-be-using-https/" rel="self"/>
    <link href="https://chameth.com/"/>
    <icon>https://chameth.com/favicon.png</icon>
    <updated>2026-09-01T00:00:00Z</updated>
    <id>https://chameth.com/</id>
    <author>
        <name>Chris Smith</name>
    </author>
    <entry>
        <title>Monthly Meanderings: August 2026</title>
        <link href="https://chameth.com/monthly-meanderings-2026-08/"/>
        <updated>2026-09-01T00:00:00Z</updated>
        <id>https://chameth.com/monthly-meanderings-2026-08/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Another month, another edition of “What’s Chris been up to?”. Fun fact: I very nearly published this post with a “[intro]” placeholder here instead of this
paragraph, despite proofreading it multiple times. “Yep, that’s where the intro will go, all good”. Now instead we have this weirdly meta introduction.&lt;/p&gt;
&lt;h3 id=&#34;website-updates-and-other-projects&#34;&gt;Website updates and other projects&lt;/h3&gt;
&lt;p&gt;A few website updates this month, and one of them neatly addresses the “other projects” bit too. First, I’ve added a new &lt;a href=&#34;https://chameth.com/fitness/&#34;&gt;fitness page&lt;/a&gt; which has some stats
and information about my cycling and running. I’ve also added some fitness-related widgets to support that page and these monthly summaries, and a new music one you can
see a bit further down.&lt;/p&gt;
&lt;p&gt;I’ve also added what I think is quite a fun new feature: a &lt;a href=&#34;https://chameth.com/feeds/posts/build/&#34;&gt;post feed builder&lt;/a&gt; that lets you build RSS feeds containing
only posts that are semantically similar (or dissimilar) to other posts. So if you want to only hear about my fitness journey you can pin a few of those
posts, or if you want to exclude posts that talk about LLMs you can exclude a few of those. It’s basically super-charged fuzzy tags, but it means I don’t
have to actually tag things.&lt;/p&gt;
&lt;p&gt;I blogged about &lt;a href=&#34;https://chameth.com/building-a-family-of-single-user-services/&#34;&gt;building a family of single-user services&lt;/a&gt; which is where most of my coding
energy went this month. Those projects were almost entirely authored by LLMs, and I’m not hating the process. The models have got a lot better at coding,
and I enjoyed getting to focus on the bigger picture aspects rather than getting bogged down in details.
Rest assured, all the writing on my website is still 100% me. I am the load-bearing seam, here.&lt;/p&gt;
&lt;h3 id=&#34;entertainment&#34;&gt;Entertainment&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://chameth.com/monthly-meanderings-2026-03/&#34;&gt;Back in March&lt;/a&gt; I said ‘I can’t do “what I listened to last month” stats until next month’, and then for the next four months completely forgot about it.
Well, not any more! Now I come equipped with some stats about my monthly music habits:&lt;/p&gt;
&lt;div class=&#34;played-albums raised-box&#34; data-title=&#34;Top albums · 1 Aug – 31 Aug 2026&#34;&gt;
    &lt;table class=&#34;plain-table&#34;&gt;
        &lt;thead&gt;
        &lt;tr&gt;
            &lt;th scope=&#34;col&#34;&gt;&lt;/th&gt;
            &lt;th scope=&#34;col&#34;&gt;&lt;/th&gt;
            &lt;th scope=&#34;col&#34;&gt;&lt;/th&gt;
            &lt;th scope=&#34;col&#34;&gt;Album&lt;/th&gt;
            &lt;th scope=&#34;col&#34;&gt;Artist&lt;/th&gt;
            &lt;th scope=&#34;col&#34; class=&#34;numeric&#34;&gt;Unique tracks played&lt;/th&gt;
            &lt;th scope=&#34;col&#34; class=&#34;numeric&#34;&gt;Total tracks played&lt;/th&gt;
        &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;1&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #4&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/190/cover.jpg&#34; alt=&#34;Cover art for Fallen&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;Fallen&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Evanescence&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;8&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;40&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;2&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #5&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/341/cover.jpg&#34; alt=&#34;Cover art for Love, Drugs &amp;amp; Misery&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;Love, Drugs &amp;amp; Misery&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Eva Under Fire&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;12&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;32&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;3&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #10&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/378/cover.jpg&#34; alt=&#34;Cover art for NEON VOID&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;NEON VOID&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Sumo Cyco&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;6&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;23&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;4&lt;/td&gt;
            &lt;td class=&#34;movement movement-down&#34; title=&#34;Down from #1&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-down&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 13l-6 6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 13l6 6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/522/cover.jpg&#34; alt=&#34;Cover art for The Strange Case of…&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;The Strange Case of…&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Halestorm&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;11&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;21&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;5&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #7&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/120/cover.jpg&#34; alt=&#34;Cover art for Coming in Hot&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;Coming in Hot&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;DIAMANTE&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;9&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;20&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;6&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #8&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/180/cover.jpg&#34; alt=&#34;Cover art for Everest&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;Everest&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Halestorm&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;7&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;20&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;7&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #126&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/227/cover.jpg&#34; alt=&#34;Cover art for Glory Days&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;Glory Days&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Little Mix&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;5&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;20&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;8&lt;/td&gt;
            &lt;td class=&#34;movement movement-down&#34; title=&#34;Down from #3&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-down&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 13l-6 6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 13l6 6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/212/cover.jpg&#34; alt=&#34;Cover art for From Zero&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;From Zero&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;Linkin Park&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;9&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;19&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;9&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #78&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/310/cover.jpg&#34; alt=&#34;Cover art for KPop Demon Hunters (Soundtrack from the Netflix Film)&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;KPop Demon Hunters (Soundtrack from the Netflix Film)&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;KPop Demon Hunters Cast&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;7&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;19&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td class=&#34;position&#34;&gt;10&lt;/td&gt;
            &lt;td class=&#34;movement movement-up&#34; title=&#34;Up from #430&#34;&gt;
                &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;16&#34; height=&#34;16&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; class=&#34;icon icon-tabler icons-tabler-outline icon-tabler-arrow-up&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke=&#34;none&#34; d=&#34;M0 0h24v24H0z&#34; fill=&#34;none&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M12 5l0 14&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M18 11l-6 -6&#34;&gt;&lt;/path&gt;&lt;path d=&#34;M6 11l6 -6&#34;&gt;&lt;/path&gt;&lt;/svg&gt;
            &lt;/td&gt;
            &lt;td class=&#34;art&#34;&gt;
                &lt;img src=&#34;https://chameth.com/music/albums/387/cover.jpg&#34; alt=&#34;Cover art for No Need to Argue&#34; loading=&#34;lazy&#34;/&gt;
            &lt;/td&gt;
            &lt;td&gt;No Need to Argue&lt;/td&gt;
            &lt;td class=&#34;artist&#34;&gt;The Cranberries&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;6&lt;/td&gt;
            &lt;td class=&#34;numeric&#34;&gt;19&lt;/td&gt;
        &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;I suspect I won’t show this every month, as it’s probably going to be quite same-y. I, shockingly, tend to play music that I like more than that which I don’t.
I’ll usually either put on my “favourites” playlist, or my “daily mix” playlist which biases higher-rated tracks over lower ones. So effectively this just
becomes a noisy view over how highly I’ve rated the tracks in an album. Maybe I can control for that, but then I’m not sure what it’d actually be showing…
“Here are all the albums I played this month that I don’t usually play because I don’t like them as much as the other albums I’m not showing any more”?
It’s a bit wordy. Back to the drawing board with that idea, I think.&lt;/p&gt;
&lt;p&gt;I was away for a few weeks this month, including a few days at a small LAN event. Being at a computer gaming event meant that we, naturally, played some board games.
Apparently I hit an h-index of 23 from these plays. That’s 23 games I’ve played at least 23 times each. I’ve been at 22 since December last year: obviously
the higher the number goes, the harder it is to reach. I also go on and off games (and the whole hobby at times), which doesn’t help on that front. Anyway, here’s
&lt;del&gt;Wonderwall&lt;/del&gt; the plays for this month:&lt;/p&gt;
&lt;ul class=&#34;played-boardgames&#34;&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Codenames (2015)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/178900/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/178900/image.jpg&#34; alt=&#34;Box art of Codenames&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;6 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Just One (2018)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/254640/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/254640/image.jpg&#34; alt=&#34;Box art of Just One&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;3 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Martian Fluxx (2009)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/35369/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/35369/image.jpg&#34; alt=&#34;Box art of Martian Fluxx&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;3 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Arkham Horror: Lovecraft Letter (2025)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/424784/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/424784/image.png&#34; alt=&#34;Box art of Arkham Horror: Lovecraft Letter&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Take 5 (1994)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/432/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/432/image.jpg&#34; alt=&#34;Box art of Take 5&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No films this month, but my &lt;a href=&#34;https://chameth.com/wow/&#34;&gt;World of Warcraft&lt;/a&gt; habit has picked back up with the launch of the new season. They’ve made Mistweaver Monk, my previous specialisation, a
lot less fun to play, so I’m focusing on one of my many alts: a Restoration Shaman:&lt;/p&gt;
&lt;div class=&#34;wow-char-grid&#34;&gt;
&lt;div class=&#34;wow-char raised-box&#34; data-title=&#34;World of Warcraft Character Data&#34;&gt;
&lt;div class=&#34;overview&#34;&gt;
&lt;img src=&#34;https://chameth.com/wow/characters/Hirameth.png&#34; alt=&#34;Hirameth&#34; loading=&#34;lazy&#34;/&gt;
&lt;p class=&#34;detail&#34;&gt;Level 90&lt;/p&gt;
&lt;p class=&#34;detail&#34;&gt;Female Dwarf&lt;/p&gt;
&lt;p class=&#34;detail&#34;&gt;&lt;span class=&#34;wow-class-shaman&#34;&gt;Restoration Shaman&lt;/span&gt;&lt;/p&gt;
&lt;p class=&#34;detail&#34;&gt;309 average item level&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;info&#34;&gt;
&lt;h3 class=&#34;plain-header&#34;&gt;Hirameth&lt;span class=&#34;realm&#34;&gt;-Terenas&lt;/span&gt;&lt;/h3&gt;
&lt;h4 class=&#34;plain-header&#34;&gt;Professions&lt;/h4&gt;
&lt;table class=&#34;plain-table professions&#34;&gt;
&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Midnight Blacksmithing&lt;/td&gt;&lt;td&gt;&lt;progress class=&#34;tier-progress&#34; value=&#34;41&#34; max=&#34;100&#34;&gt;&lt;/progress&gt;&lt;/td&gt;&lt;td class=&#34;tier-count&#34;&gt;41/100&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Midnight Inscription&lt;/td&gt;&lt;td&gt;&lt;progress class=&#34;tier-progress&#34; value=&#34;72&#34; max=&#34;100&#34;&gt;&lt;/progress&gt;&lt;/td&gt;&lt;td class=&#34;tier-count&#34;&gt;72/100&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Midnight Fishing&lt;/td&gt;&lt;td&gt;&lt;progress class=&#34;tier-progress&#34; value=&#34;35&#34; max=&#34;300&#34;&gt;&lt;/progress&gt;&lt;/td&gt;&lt;td class=&#34;tier-count&#34;&gt;35/300&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 class=&#34;plain-header&#34;&gt;Mythic+&lt;/h4&gt;
&lt;table class=&#34;plain-table mythic-plus&#34;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Altar of Fangs&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+10&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;23:10&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;329&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Den of Nalorakk&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+10&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;27:36&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;325&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Kings&amp;#39; Rest&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+12&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;28:57&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;370&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Murder Row&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+12&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;28:37&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;371&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Ruby Life Pools&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+11&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;24:28&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;340&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Temple of Sethraliss&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+10&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;30:57&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;321&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;The Blinding Vale&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+10&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;24:38&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;327&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&#34;dungeon&#34;&gt;Voidscar Arena&lt;/td&gt;
&lt;td class=&#34;level&#34;&gt;+10&lt;/td&gt;
&lt;td class=&#34;duration&#34;&gt;22:37&lt;/td&gt;
&lt;td class=&#34;rating&#34;&gt;329&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;total&#34;&gt;
&lt;th colspan=&#34;3&#34; class=&#34;plain-header&#34;&gt;Total M+ rating&lt;/th&gt;
&lt;td class=&#34;rating&#34;&gt;2711&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&#34;links&#34;&gt;
&lt;a href=&#34;https://worldofwarcraft.blizzard.com/en-gb/character/eu/terenas/hirameth&#34;&gt;View on blizzard.com&lt;/a&gt;
&lt;a href=&#34;https://raider.io/characters/eu/terenas/Hirameth&#34;&gt;View on raider.io&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I don’t quite like it as much as Mistweaver in season 1, but it’s a lot nicer than Mistweaver in season 2. You can actually make health bars move when you press your healing buttons, rather than
ignoring half of them because they’re not worth using.&lt;/p&gt;
&lt;h3 id=&#34;fitness&#34;&gt;Fitness&lt;/h3&gt;
&lt;p&gt;My running kick is still going. I’ve “officially” finished the couch-to-5k programme I was doing, and I actually hit 5k on the last day of the programme. I didn’t actually mean to do that:
I was saving the 5k run for this week, but by the time I noticed I’d run “too far” it was close enough that I just kept going. I have an actual 5k race coming up
this month, which is exciting. Once that’s over I’m planning to work my way up to 10k. I’ve added a few widgets to keep track of some stats:&lt;/p&gt;
&lt;div class=&#34;workout-summary-sections&#34;&gt;
&lt;div class=&#34;workout-summary-section raised-box&#34; data-title=&#34;Cycling · 1 Aug – 31 Aug 2026&#34;&gt;
&lt;div class=&#34;stat-row&#34;&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;3&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;activities&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;6h 5m&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;total time&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;103.6km&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;total distance&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;42.3km&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;longest distance&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class=&#34;workout-summary-pbs&#34;&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;1km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;2:17&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;1:52&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;2km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;5:34&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;4:13&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;5km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;14:51&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;12:32&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;10km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;36:00&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;27:21&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;20km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;1:43:33&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;1:13:24&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;30km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;no previous&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;1:54:25&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;40km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;no previous&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;2:55:52&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&#34;workout-summary-section raised-box&#34; data-title=&#34;Running · 1 Aug – 31 Aug 2026&#34;&gt;
&lt;div class=&#34;stat-row&#34;&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;12&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;activities&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;6h 16m&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;total time&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;43.1km&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;total distance&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;stat&#34;&gt;
&lt;p class=&#34;stat-value&#34;&gt;5km&lt;/p&gt;
&lt;p class=&#34;stat-label&#34;&gt;longest distance&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class=&#34;workout-summary-pbs&#34;&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;800m&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;5:56&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;6:02&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;1km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;7:35&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;7:36&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;1 mile&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;12:28&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;12:16&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;2km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;15:35&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;15:16&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;3km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;24:32&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;23:05&lt;/span&gt;
&lt;/li&gt;
&lt;li class=&#34;workout-summary-pb&#34;&gt;
&lt;span class=&#34;pb-trophy&#34;&gt;🏆️&lt;/span&gt;
&lt;span class=&#34;pb-label&#34;&gt;New PB&lt;/span&gt;
&lt;span class=&#34;pb-distance&#34;&gt;5km&lt;/span&gt;
&lt;span class=&#34;pb-previous&#34;&gt;no previous&lt;/span&gt;
&lt;span class=&#34;pb-time&#34;&gt;38:40&lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As well as the running, I did a couple of long (for me) cycle rides, clocking in at around 40 km. It’s a fun loop, but both times I did it I started flagging towards the end. The second time
I made sure to eat and drink plenty along the way, and my legs still raised objections about halfway round. My next goal is 50 km which would let me get to the next town over and back but
the route has a lot more elevation to go with its increased length, so it’s probably going to be quite a bit more taxing. I’m not sure when I’ll attempt that, as the weather is starting to
turn. I was previously bemused when people mentioned “cycling seasons” and switching to indoor trainers. Then I wanted to go out when it was raining, and suddenly I understood. Running in
the rain: surprisingly pleasant; cycling in the rain: no thank you.&lt;/p&gt;
&lt;h3 id=&#34;around-the-web&#34;&gt;Around the web&lt;/h3&gt;
&lt;h4 id=&#34;hacker-news-in-uncompromised-detailhttpsvalerockspostshacker-news&#34;&gt;&lt;a href=&#34;https://vale.rocks/posts/hacker-news&#34;&gt;Hacker News In Uncompromised Detail&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When I first read the title my gut reaction was “I know everything I need to know about Hacker News, right?”.
The title is accurate though. There’s so much interesting stuff, presented really cleanly. It’s a good read.&lt;/p&gt;
&lt;h4 id=&#34;a-proposal-for-new-netflix-content-rating-iconshttpsericwbaileywebsitepublisheda-proposal-for-new-netflix-content-rating-icons&#34;&gt;&lt;a href=&#34;https://ericwbailey.website/published/a-proposal-for-new-netflix-content-rating-icons/&#34;&gt;A proposal for new Netflix content rating icons&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Another dry sounding title, another fun article. It starts with a treatise on rating systems and
ends with a lovely satirical list of rating ideas.&lt;/p&gt;
&lt;h4 id=&#34;find-git-commits-by-commit-message-texthttpshamvockecombloggit-revisions-by-text&#34;&gt;&lt;a href=&#34;https://hamvocke.com/blog/git-revisions-by-text/&#34;&gt;Find Git commits by commit message text&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I like to think I’m relatively well versed in how to use Git. I can do an interactive rebase
and everything! This tip from Ham was new to me, though, and is incredibly useful.&lt;/p&gt;
&lt;h4 id=&#34;novice-marathon-training-planhttpswwwhalhigdoncomtraining-programsmarathon-trainingnovice-1-marathon&#34;&gt;&lt;a href=&#34;https://www.halhigdon.com/training-programs/marathon-training/novice-1-marathon/&#34;&gt;Novice Marathon Training Plan&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Hal Higdon has a whole bunch of training plans. He literally wrote the book on marathon training.
I’ll hopefully be following this plan next year, assuming I manage the 5k, 10k and half-marathon training!
This would be the perfect plan for someone who’s run a half marathon a while ago, and is tempted
to join me in my “marathon before I’m 40” goal…&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Building a family of single-user services</title>
        <link href="https://chameth.com/building-a-family-of-single-user-services/"/>
        <updated>2026-08-27T00:00:00Z</updated>
        <id>https://chameth.com/building-a-family-of-single-user-services/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Last month I &lt;a href=&#34;https://chameth.com/tracking-pbs-without-the-dark-patterns/&#34;&gt;made and wrote about&lt;/a&gt; a personal service
to track my workouts and record personal bests. Since then, things have escalated. I now have eight different
services running in the same “family”:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collegiate Room&lt;/td&gt;
&lt;td&gt;Simple weather overview for my current location&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;German Mall&lt;/td&gt;
&lt;td&gt;LLM broker for use by other services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gloss White&lt;/td&gt;
&lt;td&gt;Weight tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Olive Crosses&lt;/td&gt;
&lt;td&gt;Central service hub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pompei Band&lt;/td&gt;
&lt;td&gt;Workout and personal best tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Carp&lt;/td&gt;
&lt;td&gt;Spaced repetition system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tiger Island&lt;/td&gt;
&lt;td&gt;Reading history and library tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical Horse&lt;/td&gt;
&lt;td&gt;Location history and analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The names are all anagrams of something related to their function. Finding those anagrams brings me an unreasonable
amount of joy. Unscrambling them is an exercise left to the reader. On top of those eight, I currently have four other
service ideas sat in my todo list. It’s going to be a big family.&lt;/p&gt;
&lt;h3 id=&#34;a-postmortem-on-the-previous-hodge-podge&#34;&gt;A postmortem on the previous hodge-podge&lt;/h3&gt;
&lt;p&gt;Most of this functionality isn’t new to me. When I started out playing around with LLMs, I created a “personal data
aggregator” that just kept getting things bolted on. I &lt;a href=&#34;https://chameth.com/an-app-can-be-a-ready-meal/#what-ive-made&#34;&gt;said at the time&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My biggest just-for-me project is a web app that I started to help me aggregate film recommendations. It’s since morphed into a general personal data aggregation service: it deals with data from GitHub, Todoist, Letterboxd, TMDB, Healthkit, and others. It also lets me make re-orderable lists, store recipes, and more. Parts of this could definitely be open sourced, and I might carve them out at some point, but it’s mostly a glorious hodge-podge of things specific to me. Having all these services in one place lets me make quick and dirty automations, for example: when I create a Todoist note on my phone or watch, I often forget to set the due date, so it doesn’t show up in the “Today” view. It was literally a few lines of code to plumb things together so any inbox task without a due date gets set to today automatically.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a twist that &lt;em&gt;nobody&lt;/em&gt; could see coming, it turns out that a “glorious hodge-podge” is actually quite hard to maintain
and very annoying to work with. It didn’t help that it had a fairly extensive Svelte frontend and I really am not a fan
of JavaScript. I ended up using it less and less just because it wasn’t fun to use or work on, and I didn’t want to
waste the limited LLM tokens on doing massive refactors or reworks.&lt;/p&gt;
&lt;p&gt;I’ve got almost two decades of professional software development experience under my belt, so you’d think I would
have learnt the lessons on how to write maintainable software. Hell, my CV even mentions that as something I’m
particularly good at. So what went wrong?&lt;/p&gt;
&lt;p&gt;There were a few factors. One of the obvious things to blame is that it was written mostly with LLMs.
Most of that blame isn’t very honest, though. In the year or so since, LLMs have definitely got better at writing
good code; but I was manually reviewing all the code at the time, and telling it quite carefully what to implement
and how to do it. So the buck really stops with me.&lt;/p&gt;
&lt;p&gt;I think it’s actually more because it was my &lt;em&gt;first&lt;/em&gt; larger project using LLMs. It’s a bit like learning a new
programming language. I don’t think the first sizable project I’ve written in any language has ever been any
good. You can read and learn as much as you want, but you need to actually run into some problems headfirst to
get a grip on how the language works. Or at least I do. LLM coding agents are basically the same deal.&lt;/p&gt;
&lt;p&gt;What the LLMs actually did was mask several problems. The architecture wasn’t right for how the service developed.
It started out as a single-purpose app and gradually got things bolted on, without any major changes. Everything
ended up in horizontal slices: a massive database layer with every query used by every part of the app, a massive
HTTP layer, and so on. Working on a single feature became a tap dance all over the source tree. This sort of
friction is normally quite apparent when you’re writing code by hand, and at some point it hurts enough that
you throw in the towel and do some refactoring. But the LLM will happily plod on without exposing that pain,
so the project needed a more active kind of architecture management that it just didn’t get.&lt;/p&gt;
&lt;p&gt;The other problem they covered up was how brittle and unmaintainable the JavaScript frontend was. I’m not
even sure how I ended up with a Svelte frontend in hindsight. It’s my preferred framework, but I still only
reach for it as a last resort when there’s no other way to avoid using one. It seems like there were lots of
ways to avoid it here, but I seem to have… well… avoided them. Anyway, each feature got its own slew of
Svelte components, without much thought to reusability, shared patterns, or anything sensible. Some of them
were just thin wrappers around data supplied by Go, others had vast swathes of logic in them, with no real
rhyme or reason as to which way that would fall. It’s the same issue as before: a human would look at it,
say “WTF?” and suggest tidying it up; instead, the LLM just gets on with what you tell it to do.&lt;/p&gt;
&lt;p&gt;There’s also a big non-LLM factor: one of the primary reasons all of this unrelated functionality got
tossed into the same app was that I’d previously worked on a few projects with a microservice architecture
and really didn’t like it. My conclusion was they only really worked in large environments where you can
dedicate people or teams to working on all the boilerplate that happens from maintaining lots of
interconnected projects. Dumping everything and the kitchen sink into one badly architected monolith was,
perhaps, not the best rebound from that.&lt;/p&gt;
&lt;h3 id=&#34;pompei-band-and-beyond&#34;&gt;Pompei Band and beyond&lt;/h3&gt;
&lt;p&gt;When I wanted to implement &lt;del&gt;Strava at home&lt;/del&gt; my PB tracking app, it seemed fairly natural to build it out
as a new service, rather than bolt it on to the slowly decomposing hodge-podge that was giving off a funny
smell. Then when I wanted a weather dashboard, why not do it in the same style as Pompei Band? The same
serving architecture, the same page layout… I could even come up with a similar weird two-word name!&lt;/p&gt;
&lt;p&gt;Then wouldn’t it be nice if the weather dashboard knew where I was, so it could show the local weather?
I could just build that functionality in, but it’d also be a good opportunity to carve out the location
history feature from my old service and make a new, shinier one. Then basically every time I even thought
about going near the old service, I mentally sketched out a replacement service.&lt;/p&gt;
&lt;figure class=&#34;image right&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/building-a-family-of-single-user-services/oc.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/building-a-family-of-single-user-services/oc.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/building-a-family-of-single-user-services/oc.png&#34; alt=&#34;A screenshot of Olive Crosses, showing links to other services with icons based on their two-word names&#34; loading=&#34;lazy&#34; width=&#34;1230&#34; height=&#34;619&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;Olive Crosses showing links to the other services&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;At one point I had the thought that it’d be nice if the services could all link to one another, but I
didn’t want to have to touch every service whenever I added a new one. So I made a “hub” service, which
maintains the One True Catalogue, and provides a bit of JavaScript the others can all embed to add a
navigation sidebar.&lt;/p&gt;
&lt;p&gt;So after complaining about microservices and JavaScript, it sounds like I have landed on microservices
(or at least miniservices) and JavaScript? Sort of yes, but sort of no. Each service is still its own
thing and makes sense independent of the others. There are some cross-service dependencies, but they’re
very simple and don’t have the same cognitive or boilerplate overhead as a login service that talks to
an authentication service that queries a user manager and so on. And as for the JavaScript, it’s almost
exclusively used for progressive enhancement and a few limited client-side visual things like
maps and graphs. All of the logic lives in Go, which is a lot easier to maintain and test, and all of
the pages are simple Go templates.&lt;/p&gt;
&lt;p&gt;Having these services built in a way that I actually like has motivated me to play around a lot more
with new features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My workout tracking app pulls photos from my private &lt;a href=&#34;https://immich.app&#34;&gt;Immich&lt;/a&gt; server that were
taken during workouts, and shows them alongside. Now I can see all my obligatory end-of-run selfies
in one place.&lt;/li&gt;
&lt;li&gt;The location history app can detect trips away from home, and get an LLM to automatically title them.
My most recent, very exotic, trip has the title “A fortnight in Milton Keynes and Coventry”. Each
trip gets its own little map, and in the future I want to pull in images like with workouts.&lt;/li&gt;
&lt;li&gt;My weight tracking app now exports weigh-ins to Garmin, as it doesn’t fully integrate with Apple
Health (it will export its own weights, but not import others, like the ones from my Withings scales).
Stupid walled gardens, but thankfully I can fix it myself.&lt;/li&gt;
&lt;li&gt;My book tracking app automatically cleans up the titles of books from the nonsense provided by Amazon
to something more palatable. “Killing Eve: Long Shot: A twist on obsession, betrayal and revenge from
Luke Jennings, author of the TV sensation Killing Eve” becomes “Long Shot (Killing Eve #5)”. It does
this by passing the title to an LLM with a bunch of rules.&lt;/li&gt;
&lt;li&gt;The hub generates me a snippet of Tailscale configuration that defines the minimal grants needed to
allow the intra-service dependencies to work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The LLM integrations were inspired by my friend &lt;a href=&#34;https://dataforce.org.uk/&#34;&gt;Shane&lt;/a&gt; who recently
demonstrated an inventory tracking app he’d made, which used Haiku to process images of boxes and
describe the contents. I’ve dabbled with LLM integration before, and always disliked the process
of fiddling with the prompts, and debugging when the LLM gave a nonsensical response. So I built
German Mall, which makes it a lot easier. It lets me define a “workflow” consisting of a system
prompt, initial message, and expected response format. I can browse past runs, tweak the prompt,
rerun them to see the change, all without touching the services using them. Quick iteration loops
are the best. German Mall also provides markdown documentation for each workflow, so integrating
it downstream is simply a case of pointing a coding agent at the right documentation endpoint.&lt;/p&gt;
&lt;figure class=&#34;image full&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/building-a-family-of-single-user-services/gm.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/building-a-family-of-single-user-services/gm.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/building-a-family-of-single-user-services/gm.png&#34; alt=&#34;A screenshot of German Mall, showing the workflow configuration for tidying book titles: a form with fields for description, system prompt, user template, output schema, model, max tokens and temperature.&#34; loading=&#34;lazy&#34; width=&#34;1482&#34; height=&#34;1080&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;The “tidy book titles” workflow in German Mall&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It’s not all fun and games: having a bunch of services all following the same pattern means
you need to do cross-cutting maintenance on them now and then. But that’s surprisingly easy with LLMs.
I put all the projects in a common folder, and I launch cross-cutting tasks from that folder. Usually
I’ll make the change in one project, and then the cross-cutting task is simply “Look at commit XYZ in
./foo, make the same change to the other projects”.&lt;/p&gt;
&lt;p&gt;I’ve also ended up with a shared library used by all the projects to cut down on some boilerplate.
That’s normally something I’d resist, especially with personal projects, just because the extra overhead
of working in a separate project, managing releases of it, and so on, is a bit annoying. But, again,
LLMs can do almost all of that grunt work. They effectively reduce the “cost” of maintaining separate
services to a negligible level, leaving me to focus on the more fun aspects like coming up with new names.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Monthly Meanderings: February 2026</title>
        <link href="https://chameth.com/monthly-meanderings-2026-02/"/>
        <updated>2026-03-01T00:00:00Z</updated>
        <id>https://chameth.com/monthly-meanderings-2026-02/</id>
        <content xml:lang="en" type="html">&lt;p&gt;It doesn’t feel like a whole month has gone past since I wrote &lt;a href=&#34;https://chameth.com/monthly-meanderings-2026-01/&#34;&gt;the last instalment of Monthly Meanderings&lt;/a&gt;, even allowing for how short a month February is. For more context on this series, you can check out &lt;a href=&#34;https://chameth.com/monthly-meanderings-2025-12/&#34;&gt;the introduction to the first edition&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;website-updates&#34;&gt;Website updates&lt;/h3&gt;
&lt;p&gt;I only wrote one new blog post this month: &lt;a href=&#34;https://chameth.com/just-a-nod/&#34;&gt;Just a nod&lt;/a&gt;, which is about the “nod” button I added to the bottom of most pages. I did a lot of other little bits and pieces, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My blog posts are now automatically posted to &lt;a href=&#34;https://bsky.app/profile/posts.chameth.com&#34;&gt;a dedicated Bluesky account&lt;/a&gt;, and posts now include syndication links at the bottom.&lt;/li&gt;
&lt;li&gt;The site now tracks how long each request takes to generate along with how many SQL queries were used. You can see the details for the current request by hovering/tapping over the pi symbol at the bottom right of a page. To understand why it’s a pi symbol, you should watch &lt;a href=&#34;https://chameth.com/films/the-net-1995/&#34;&gt;The Net&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Speaking of films, I redid the star rating rendering so instead of unicode stars it uses some hand-drawn pixel art stickers. They’re somewhat randomised, so they don’t look repetitive. This is what it now looks like:
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
.&lt;/li&gt;
&lt;li&gt;I spent some time tweaking various styles and layouts so everything works nicely on smaller screens. I try to make sure these things work when I make them, but it’s easy to miss a particular interaction, or make an innocent-seeming change that breaks tiny screens.&lt;/li&gt;
&lt;li&gt;I added a new page that shows stats about &lt;a href=&#34;https://chameth.com/walks/&#34;&gt;my walks&lt;/a&gt;, based on my Apple Health data. I had a private view of this for a while, but decided there’s no reason it couldn’t be more public.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://chameth.com/films/&#34;&gt;films page&lt;/a&gt; has gained a search box, to directly find my review of a particular film. I used &lt;a href=&#34;https://css-tricks.com/css-anchor-positioning-guide/&#34;&gt;CSS anchor positioning&lt;/a&gt; for the results panel. Modern CSS is fun!&lt;/li&gt;
&lt;li&gt;I fixed the &lt;a href=&#34;https://chameth.com/prints/&#34;&gt;3D prints&lt;/a&gt; page being utterly broken in numerous ways. It showed up on my shiny new “how many SQL queries does each page do?” dashboard, as it was doing multiple queries for each individual print instead of just getting all the data in one go. Then I noticed a badly written redirect rule had broken all the images and download links. Whoops!&lt;/li&gt;
&lt;li&gt;I did a lot of under-the-hood cleaning, most of which won’t be visible. Besides just making me happy, this means the contact form and nod buttons now work with Javascript disabled.&lt;/li&gt;
&lt;li&gt;Finally, I added a page that shows my &lt;a href=&#34;https://chameth.com/boardgames/&#34;&gt;board game plays&lt;/a&gt;. The data comes from exports from &lt;a href=&#34;https://www.bgstatsapp.com/&#34;&gt;bgstats&lt;/a&gt;. I have a bunch of ideas for other things to do with that data, but haven’t got around to it yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Phew. After writing all that out it feels like a really long month, not a short one!&lt;/p&gt;
&lt;h3 id=&#34;other-projects&#34;&gt;Other projects&lt;/h3&gt;
&lt;p&gt;Not much going on with my other projects. The only big thing was &lt;a href=&#34;https://github.com/csmith/goplum&#34;&gt;goplum&lt;/a&gt;, my self-hosted monitoring/alerting tool, getting a 1.0 release. It adds a reminder feature so you can get alerted repeatedly if a service is down. It also reworks how plugins work so they’re compile-time instead of trying to be clever and dynamic, as that never really gave any benefits.&lt;/p&gt;
&lt;p&gt;I’m still continuing my migration of projects to a private &lt;a href=&#34;https://forgejo.org/&#34;&gt;Forgejo&lt;/a&gt; instance. All of my personal repos are now sourced there, and mirrored out to GitHub, except one: my &lt;a href=&#34;https://github.com/csmith/dockerfiles&#34;&gt;Dockerfiles&lt;/a&gt;. I’m not sure how I want to approach that yet, as the action that does the updating is pretty involved. I also have some repositories split off into their own GitHub organisations which I haven’t got around to mirroring yet.&lt;/p&gt;
&lt;h3 id=&#34;entertainment&#34;&gt;Entertainment&lt;/h3&gt;
&lt;p&gt;Unlike the past few months, I didn’t touch many video games in February. The ones I’d been dabbling with didn’t really hook me enough to make me keep going back. I made up for it with lots of other media forms though. First up, a whole bunch of films:&lt;/p&gt;
&lt;ol class=&#34;watched-films&#34;&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/black-swan-2010/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/242/poster.jpg&#34; alt=&#34;Poster of Black Swan&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-02&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/the-net-1995/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/243/poster.jpg&#34; alt=&#34;Poster of The Net&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-03&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/office-space-1999/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/244/poster.jpg&#34; alt=&#34;Poster of Office Space&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-04&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/the-silence-of-the-lambs-1991/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/245/poster.jpg&#34; alt=&#34;Poster of The Silence of the Lambs&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-07&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/big-night-1996/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/246/poster.jpg&#34; alt=&#34;Poster of Big Night&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-10&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/the-cabin-in-the-woods-2012/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/247/poster.jpg&#34; alt=&#34;Poster of The Cabin in the Woods&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-11&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/knock-at-the-cabin-2023/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/248/poster.jpg&#34; alt=&#34;Poster of Knock at the Cabin&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-12&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/the-faculty-1998/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/249/poster.jpg&#34; alt=&#34;Poster of The Faculty&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-13&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/final-destination-2000/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/250/poster.jpg&#34; alt=&#34;Poster of Final Destination&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-13&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/get-out-2017/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/251/poster.jpg&#34; alt=&#34;Poster of Get Out&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-14&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/no-country-for-old-men-2007/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/252/poster.jpg&#34; alt=&#34;Poster of No Country for Old Men&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-02-17&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I won’t write too much about them here — you can click through to read my reviews if you want — other than to call out the three excellent horror films I hadn’t seen before: &lt;a href=&#34;https://chameth.com/films/black-swan-2010/&#34;&gt;Black Swan&lt;/a&gt;, &lt;a href=&#34;https://chameth.com/films/the-cabin-in-the-woods-2012/&#34;&gt;The Cabin in the Woods&lt;/a&gt;, and &lt;a href=&#34;https://chameth.com/films/get-out-2017/&#34;&gt;Get Out&lt;/a&gt;. Not so long ago I would’ve said that I didn’t enjoy horror films, now they’re some my favourites.&lt;/p&gt;
&lt;p&gt;I don’t have any TV show tracking on my website (yet?), as I haven’t really watched much recently. This month I started watching &lt;a href=&#34;https://www.themoviedb.org/tv/250307-the-pitt&#34;&gt;The Pitt&lt;/a&gt; though, and it rapidly become one of my favourite shows. By “started watching” I mean “watched every aired episode of both season 1 and season 2”. I highly recommend it. The only problem is that it’s hard to find anything to watch afterwards, as nothing else can quite measure up.&lt;/p&gt;
&lt;p&gt;I’ve also been binging a book series: &lt;a href=&#34;https://www.amazon.co.uk/dp/B0DT7G27HH&#34;&gt;Beneath the Dragoneye Moons&lt;/a&gt;. It’s a LitRPG series: basically a fantasy setting that borrows systems from an RPG, like classes and levelling. Something about the genre really works for me, and Beneath the Dragoneye Moons is one of the more interesting series I’ve come across in the genre. I’ve been going through the series at the rate of about a book a day.&lt;/p&gt;
&lt;p&gt;Finally, board games! Nothing particularly notable, but now I can embed a pretty display of what I actually played:&lt;/p&gt;
&lt;ul class=&#34;played-boardgames&#34;&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Can&amp;#39;t Stop (1980)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/41/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/41/image.png&#34; alt=&#34;Box art of Can&amp;#39;t Stop&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;6 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Cartographers (2019)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/263918/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/263918/image.png&#34; alt=&#34;Box art of Cartographers&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;4 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;My Shelfie: The Dice Game (2024)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/411543/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/411543/image.jpg&#34; alt=&#34;Box art of My Shelfie: The Dice Game&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;4 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Super Mega Lucky Box (2021)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/341530/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/341530/image.png&#34; alt=&#34;Box art of Super Mega Lucky Box&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;4 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;7 Wonders Dice (2025)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/446231/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/446231/image.jpg&#34; alt=&#34;Box art of 7 Wonders Dice&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Let&amp;#39;s Go! To Japan (2024)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/368173/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/368173/image.jpg&#34; alt=&#34;Box art of Let&amp;#39;s Go! To Japan&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Martian Dice (2011)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/99875/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/99875/image.png&#34; alt=&#34;Box art of Martian Dice&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Pickomino (2005)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/15818/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/15818/image.jpg&#34; alt=&#34;Box art of Pickomino&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Space Base (2018)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/242302/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/242302/image.jpg&#34; alt=&#34;Box art of Space Base&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Terraforming Mars (2016)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/167791/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/167791/image.jpg&#34; alt=&#34;Box art of Terraforming Mars&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;2 plays&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Azul: Summer Pavilion (2019)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/287954/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/287954/image.jpg&#34; alt=&#34;Box art of Azul: Summer Pavilion&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Booty Dice (2023)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/408658/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/408658/image.png&#34; alt=&#34;Box art of Booty Dice&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Castles of Mad King Ludwig (2014)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/155426/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/155426/image.jpg&#34; alt=&#34;Box art of Castles of Mad King Ludwig&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Coffee Rush (2023)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/377061/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/377061/image.jpg&#34; alt=&#34;Box art of Coffee Rush&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Flip 7 (2024)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/420087/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/420087/image.jpg&#34; alt=&#34;Box art of Flip 7&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Fluxx (1997)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/258/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/258/image.jpg&#34; alt=&#34;Box art of Fluxx&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Lodge (2026)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/452300/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/452300/image.jpg&#34; alt=&#34;Box art of Lodge&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Next Station: Paris (2024)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/403116/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/403116/image.jpg&#34; alt=&#34;Box art of Next Station: Paris&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Next Station: Tokyo (2023)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/380165/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/380165/image.jpg&#34; alt=&#34;Box art of Next Station: Tokyo&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Obsession (2018)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/231733/image.png&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/231733/image.png&#34; alt=&#34;Box art of Obsession&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
  &lt;li class=&#34;raised-box&#34;&gt;
    &lt;div class=&#34;image-container&#34; title=&#34;Ticket to Ride (2004)&#34;&gt;
      &lt;img class=&#34;background&#34; src=&#34;https://chameth.com/boardgames/9209/image.jpg&#34; aria-hidden=&#34;true&#34; loading=&#34;lazy&#34;/&gt;
      &lt;img class=&#34;foreground&#34; src=&#34;https://chameth.com/boardgames/9209/image.jpg&#34; alt=&#34;Box art of Ticket to Ride&#34; loading=&#34;lazy&#34;/&gt;
    &lt;/div&gt;
    &lt;p&gt;1 play&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these were online via &lt;a href=&#34;https://boardgamearena.com/&#34;&gt;Board Game Arena&lt;/a&gt;. I haven’t really had time for in-person games with all the TV, films and reading!&lt;/p&gt;
&lt;h3 id=&#34;around-the-web&#34;&gt;Around the web&lt;/h3&gt;
&lt;h4 id=&#34;start-all-of-your-commands-with-a-commahttpsrhodesmillorgbrandon2009commands-with-comma&#34;&gt;&lt;a href=&#34;https://rhodesmill.org/brandon/2009/commands-with-comma/&#34;&gt;Start all of your commands with a comma&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;An old post that was doing the rounds again on Hacker News. It’s an interesting idea. I recently aliased &lt;code&gt;cc&lt;/code&gt; to launch Claude Code with some custom parameters, and it horribly backfired when I tried to compile a C program and remembered that &lt;code&gt;cc&lt;/code&gt; was part of GCC. I haven’t transitioned all my personal commands to use a prefix yet, but I might.&lt;/p&gt;
&lt;h4 id=&#34;tactical-tornado-is-the-new-defaulthttpsolanodevblogtactical-tornado&#34;&gt;&lt;a href=&#34;https://olano.dev/blog/tactical-tornado/&#34;&gt;Tactical tornado is the new default&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;An interesting post about software developers who act as “tactical tornadoes”, and how that’s basically the role that all LLMs fill. Whenever I use coding agents, I often find myself following behind them in my IDE cleaning up bits and pieces. It’s often faster than prompting them to do it. I definitely get the “cleaning up after a tornado” metaphor.&lt;/p&gt;
&lt;p&gt;Amusingly, the agents will sometimes notice that you’re tidying up after them and ascribe it to an automated process, outputting something like “the automated linter hasn’t run yet” if you fall behind. There’s probably a deeper philosophical discussion about what it means when the agent thinks that the human is the automated part of the system…&lt;/p&gt;
&lt;h4 id=&#34;my-smart-sleep-mask-broadcasts-users-brainwaves-to-an-open-mqtt-brokerhttpsaimiliosbearblogdevreverse-engineering-sleep-mask&#34;&gt;&lt;a href=&#34;https://aimilios.bearblog.dev/reverse-engineering-sleep-mask/&#34;&gt;My smart sleep mask broadcasts users’ brainwaves to an open MQTT broker&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Another one for the “the ’s’ in ‘IoT’ stands for security” books. I find it hard to actually comprehend how these things get to market. Does nobody actually think about it, or do they know full well how bad it is and just launch it anyway?&lt;/p&gt;
&lt;h4 id=&#34;the-indieweb-and-small-webhttpschristianodevpostindieweb-smallweb&#34;&gt;&lt;a href=&#34;https://christiano.dev/post/indieweb_smallweb/&#34;&gt;The IndieWeb and Small web&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Ask three people to define ‘IndieWeb’ and ‘Small web’ and you’ll get about 20 different answers. This post by Christiano almost exactly nails my own views on the terms, and explains them well. I think most personal sites (my own included) straddle both terms to some extent, but having the labels is useful in discussions.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>Monthly Meanderings: January 2026</title>
        <link href="https://chameth.com/monthly-meanderings-2026-01/"/>
        <updated>2026-02-01T00:00:00Z</updated>
        <id>https://chameth.com/monthly-meanderings-2026-01/</id>
        <content xml:lang="en" type="html">&lt;p&gt;Welcome to the second edition of my monthly meanderings. For a bit of context, you can check out &lt;a href=&#34;https://chameth.com/monthly-meanderings-2025-12/&#34;&gt;the introduction to the first edition&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;website-updates&#34;&gt;Website updates&lt;/h3&gt;
&lt;p&gt;It’s been a pretty busy month for chameth.com. Three blog posts: &lt;a href=&#34;https://chameth.com/the-meaning-of-life/&#34;&gt;The Meaning of Life&lt;/a&gt; — an entry into the &lt;a href=&#34;https://www.jeremiahlee.com/posts/2026-01-indieweb-carnival/&#34;&gt;IndieWeb carnival&lt;/a&gt; where I mostly review a book on Stoicism —  &lt;a href=&#34;https://chameth.com/surge-protectors-marketing-vs-reality/&#34;&gt;Surge Protectors: Marketing vs Reality&lt;/a&gt; which is a dump of a research rabbit hole I fell into, and &lt;a href=&#34;https://chameth.com/tailscale-docker-gotcha/&#34;&gt;An Interesting Tailscale + Docker Gotcha&lt;/a&gt; which documents a fun problem I encountered.&lt;/p&gt;
&lt;p&gt;I’ve also made a new &lt;a href=&#34;https://chameth.com/films/&#34;&gt;films&lt;/a&gt; section, which is basically my Letterboxd data but free range instead of cooped up in a silo. I imported my 200-odd reviews, and for the last few I wrote the review on my site and then copied it over to Letterboxd. That’s what the IndieWeb folks call &lt;a href=&#34;https://indieweb.org/POSSE&#34;&gt;POSSE&lt;/a&gt;: publish on your own site, syndicate elsewhere. I like the idea that my website is the canonical source of truth for all the public things I generate. I want to expand this to some other areas in the future: music, video games, board games, etc.&lt;/p&gt;
&lt;p&gt;I made most of the film components into “shortcodes”, so I can drop them into arbitrary pages or posts, like so:&lt;/p&gt;
&lt;a class=&#34;film-list raised-box plain-link&#34; data-title=&#34;Film list&#34; href=&#34;https://chameth.com/films/lists/ranking/&#34;&gt;
  &lt;h3 class=&#34;plain-header&#34;&gt;Watched films ranked&lt;/h3&gt;
  &lt;div class=&#34;poster-stack&#34;&gt;
    &lt;img src=&#34;https://chameth.com/films/265/poster.jpg&#34; alt=&#34;Poster of Midsommar&#34;/&gt;&lt;img src=&#34;https://chameth.com/films/4/poster.jpg&#34; alt=&#34;Poster of Easy A&#34;/&gt;&lt;img src=&#34;https://chameth.com/films/97/poster.jpg&#34; alt=&#34;Poster of Hackers&#34;/&gt;&lt;img src=&#34;https://chameth.com/films/25/poster.jpg&#34; alt=&#34;Poster of The Matrix&#34;/&gt;&lt;img src=&#34;https://chameth.com/films/202/poster.jpg&#34; alt=&#34;Poster of Sinners&#34;/&gt;
  &lt;/div&gt;
  &lt;div class=&#34;description&#34;&gt;&lt;p&gt;Every film I’ve watched since I started logging, ranked.&lt;/p&gt;
&lt;p&gt;Obviously super subjective, and subject to change often and arbitrarily.&lt;/p&gt;
&lt;/div&gt;
  &lt;p class=&#34;count&#34;&gt;264 films&lt;/p&gt;
&lt;/a&gt;
&lt;p&gt;Finally, I added a new widget to the bottom of most pages: a “nod” button. It’s effectively a “like” or “kudos” button but deliberately does not track how many times it’s been pressed, has no social network connotations, and won’t flood my inbox or hit rate limits if it gets spammed. If you click the button, it simply sends a message to a private IRC channel that says “Someone nodded at $URL”. I’ll probably write a bit more about it in a blog post in the future.&lt;/p&gt;
&lt;h3 id=&#34;other-projects&#34;&gt;Other projects&lt;/h3&gt;
&lt;p&gt;I only have one small non-chameth.com update: a new project called &lt;a href=&#34;https://github.com/csmith/pigeonhole/&#34;&gt;pigeonhole&lt;/a&gt; which provides a really basic web service that lets you leave messages in a named cubby, and retrieve them at a later date. I’m using it to automate adding things to my Obsidian notes from my Apple Watch. There’s lots of reasons why that isn’t as simple as it sounds. I went through a bunch of iterations to try and make it work before just writing code to fix it.&lt;/p&gt;
&lt;p&gt;I wanted to do this because I’m trying to replace Todoist with just having tasks in &lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt;. I already used Obsidian for longer form notes, but I’ve now also started using it for drafting blog posts (I’m typing this in Obsidian right now!), and trying to keep more useful day-to-day notes. I’ll probably write a blog post with more details once I’ve figured everything out.&lt;/p&gt;
&lt;p&gt;Finally, I’ve been moving a bunch of projects to a private &lt;a href=&#34;https://forgejo.org/&#34;&gt;Forgejo&lt;/a&gt; instance, with the ultimate goal of having all of my projects live there. I’m going to mirror the contents out to GitHub and maybe other places, but Forgejo will be the single source of truth, and where all the workflows/dependency wrangling/etc happens. I’ve got &lt;a href=&#34;https://renovatebot.com/&#34;&gt;Renovate&lt;/a&gt; configured to do dependency bumps, and I’m very much liking the whole setup so far. I’m saying it a lot but again: I’ll blog about it in more detail when it’s a bit further along.&lt;/p&gt;
&lt;h3 id=&#34;entertainment&#34;&gt;Entertainment&lt;/h3&gt;
&lt;p&gt;I mentioned last month that I was playing Hogwarts: Legacy. I finished that off, and have been struggling to find something to scratch the same itch. I’ve tried a whole bunch of open world games, and basically none of them work for me. They have cumbersome control schemes (yay console ports), really awkward or sluggish movement, and so on. I think I’m just too fussy, but if I’m going to sink dozens of hours into a game it shouldn’t feel annoying or like a chore!&lt;/p&gt;
&lt;p&gt;I did play through &lt;a href=&#34;https://store.steampowered.com/app/2366980/Thank_Goodness_Youre_Here/&#34;&gt;Thank Goodness You’re Here&lt;/a&gt;, which is delightfully funny but sadly only took 3.6 hours to finish with 100% of the achievements. Still highly recommend picking it up, especially when it’s on sale for under ‘10 bob’.
I’ve also started playing through Control, and I’m enjoying the ambience. There’s an insanely sharp difficulty spike for the first boss, though, which nearly made me put it down.&lt;/p&gt;
&lt;p&gt;In other entertainment, I’ve been playing a load of turn-based games on &lt;a href=&#34;https://boardgamearena.com/&#34;&gt;Board Game Arena&lt;/a&gt; , and I’ve watched a bunch of films after barely watching any last month. Here’s another of those shortcodes to show them off:&lt;/p&gt;
&lt;ol class=&#34;watched-films&#34;&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/bugonia-2025/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/234/poster.jpg&#34; alt=&#34;Poster of Bugonia&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-13&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/arrival-2016/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/235/poster.jpg&#34; alt=&#34;Poster of Arrival&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-15&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/ender-s-game-2013/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/236/poster.jpg&#34; alt=&#34;Poster of Ender&amp;#39;s Game&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-16&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/bill-ted-s-excellent-adventure-1989/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/237/poster.jpg&#34; alt=&#34;Poster of Bill &amp;amp; Ted&amp;#39;s Excellent Adventure&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-19&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/upgrade-2018/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/238/poster.jpg&#34; alt=&#34;Poster of Upgrade&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-20&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-half.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Half star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/blow-the-man-down-2019/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/239/poster.jpg&#34; alt=&#34;Poster of Blow the Man Down&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-21&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-2&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-1&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;a class=&#34;plain-link raised-box&#34; href=&#34;https://chameth.com/films/psych-2-lassie-come-home-2020/&#34;&gt;
      &lt;img src=&#34;https://chameth.com/films/241/poster.jpg&#34; alt=&#34;Poster of Psych 2: Lassie Come Home&#34; loading=&#34;lazy&#34;/&gt;
      &lt;time&gt;2026-01-26&lt;/time&gt;
      &lt;div&gt;
&lt;span class=&#34;star-rating&#34;&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-flat.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Full star&#34; class=&#34;rot-0&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;img src=&#34;https://chameth.com/star-empty.png&#34; width=&#34;28&#34; height=&#34;28&#34; alt=&#34;Empty star&#34;/&gt;&lt;/span&gt;
&lt;/div&gt;
    &lt;/a&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;around-the-web&#34;&gt;Around the web&lt;/h3&gt;
&lt;h4 id=&#34;remotely-unlocking-an-encrypted-hard-diskhttpsjyndevremotely-unlocking-an-encrypted-hard-disk&#34;&gt;&lt;a href=&#34;https://jyn.dev/remotely-unlocking-an-encrypted-hard-disk/&#34;&gt;Remotely unlocking an encrypted hard disk&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A fun post documenting using Tailscale in a very weird way to solve a relatable problem. Very much my cup of tea.&lt;/p&gt;
&lt;h4 id=&#34;i-charged-18000-for-a-static-html-pagehttpsidiallocomblog18000-dollars-static-web-page&#34;&gt;&lt;a href=&#34;https://idiallo.com/blog/18000-dollars-static-web-page&#34;&gt;I charged $18,000 for a static HTML page&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This one’s actually from 2019, but it’s the first time I’ve come across it, and it’s a fun story. As a contractor, deciding what to bill for and what not to can be a bit messy. Downtime between meetings? The ten minutes in the shower you spent thinking through a bug? It’s a lot more clear cut if the client wants you to sit in an office, twiddling your thumbs, though.&lt;/p&gt;
&lt;h4 id=&#34;oxide-rfd-using-llms-at-oxidehttpsrfdsharedoxidecomputerrfd0576&#34;&gt;&lt;a href=&#34;https://rfd.shared.oxide.computer/rfd/0576&#34;&gt;Oxide RFD: Using LLMs at Oxide&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A wonderfully well thought out piece about using LLMs in a respectful, sensible manner. I’d been thinking about writing something similar, but it wouldn’t have been anywhere near as well crafted as this. While I basically agree with it all, the part about LLM-generated text really resonates:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LLM-generated prose undermines a social contract of sorts: absent LLMs, it is presumed that of the reader and the writer, it is the writer that has undertaken the greater intellectual exertion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&#34;your-app-subscription-is-now-my-weekend-projecthttpsrselbachcomyour-sub-is-now-my-weekend-project&#34;&gt;&lt;a href=&#34;https://rselbach.com/your-sub-is-now-my-weekend-project&#34;&gt;Your app subscription is now my weekend project&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Roberto points out that monthly SaaS subscriptions start looking even less appealing when you can just prompt an alternative into existence. &lt;a href=&#34;https://chameth.com/an-app-can-be-a-ready-meal/&#34;&gt;I talked a bit about using LLMs for one-person software before&lt;/a&gt;, and it becomes even more appealing when the alternative is paying monthly for a service that keeps shoe-horning in features you don’t want, making you agree to share data with 329 “trusted partners”, and/or repeatedly ratcheting up the price.&lt;/p&gt;
&lt;h4 id=&#34;ekuls-internet-spacehttpsekulme&#34;&gt;&lt;a href=&#34;https://ekul.me/&#34;&gt;Ekul’s Internet Space&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I love the aesthetics of this personal site, and the data tracking that goes along with it. I’m also slightly aghast at the amount of Monster consumed! Makes me want to track more things and expose them on my own site.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>An interesting Tailscale + Docker gotcha</title>
        <link href="https://chameth.com/tailscale-docker-gotcha/"/>
        <updated>2026-01-29T00:00:00Z</updated>
        <id>https://chameth.com/tailscale-docker-gotcha/</id>
        <content xml:lang="en" type="html">&lt;p&gt;As I’ve &lt;a href=&#34;https://chameth.com/how-i-use-tailscale/&#34;&gt;written&lt;/a&gt; &lt;a href=&#34;https://chameth.com/avoiding-the-consequences-of-dumb-laws-with-tailscale/&#34;&gt;about&lt;/a&gt; &lt;a href=&#34;https://chameth.com/exposing-game-servers-over-tailscale/&#34;&gt;before&lt;/a&gt;, I use &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt; for a lot of things. I thought I had it set up in a reasonably secure manner, but I recently noticed a problem.&lt;/p&gt;
&lt;p&gt;I use Tailscale’s ACLs to limit what each node can access, based on the tags I apply to it. So an &lt;code&gt;app&lt;/code&gt; node can’t access anything via Tailscale, while an &lt;code&gt;integration&lt;/code&gt; or &lt;code&gt;server&lt;/code&gt; node can access things tagged with either &lt;code&gt;app&lt;/code&gt; or &lt;code&gt;integration&lt;/code&gt;. This is expressed pretty simply in the Tailscale ACL JSON:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tagOwners&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Servers that can be SSH&amp;#39;d into
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Applications that are exposed on tailscale but never connect out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:app&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Things which talk to other services over tailscale (connecting to apps etc)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;grants&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Users can access everything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;autogroup:member&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;dst&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Servers and integrations can access integrations and apps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;dst&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:app&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Over the past week I’ve been setting up a private &lt;a href=&#34;https://forgejo.org/&#34;&gt;Forgejo&lt;/a&gt; instance behind Tailscale, complete with an actions runner that runs things using a docker-in-docker container. I didn’t want the runner knowing anything about Tailscale, so I had it configured to speak to Forgejo direct over HTTP (&lt;code&gt;forgejo:3000&lt;/code&gt;) instead of using full Tailscale HTTPS URL that I use when accessing it (&lt;code&gt;http://git.example-net.ts.net/&lt;/code&gt;)&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:1&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Everything was going fine, until I forgot to do that translation… and it worked. My Forgejo action runners could access anything on my tailnet. I run several things on Tailscale that just have authentication turned off, on the basis that only authorised devices can access them. Things like the admin interface for this website. I definitely didn’t intend for any workflow I run on my git server to have access to edit my website!&lt;/p&gt;
&lt;p&gt;This wasn’t just limited to Forgejo, either. Any docker container I was running could access the tailnet. In hindsight it’s fairly obvious why: the host is running Tailscale, connected as a node tagged with my &lt;code&gt;server&lt;/code&gt; tag. That creates a &lt;code&gt;tailscale0&lt;/code&gt; interface, and automagically sets up iptables rules to route Tailscale traffic over the interface. Docker also automagically sets up iptables rules to bridge traffic, and apparently these two sets of rules interact in such a way that traffic from Docker containers is allowed to route via the &lt;code&gt;tailscale0&lt;/code&gt; interface.&lt;/p&gt;
&lt;p&gt;I say it’s fairly obvious in hindsight — there’s no reason why Docker would special case any particular host interface after all — but it still feels pretty surprising. Because both bits of software inject their own iptables rules, I never really had a good mental model for how they interact. The host Tailscale node was a completely separate building block to Docker. It would be a pain to use either of them if they didn’t do these rules, but it’s also one of the reasons I don’t really like “magical” things&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:2&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;There are lots of ways to fix this, but none of them feel particularly great. You can configure both Tailscale and Docker to not automatically fiddle with iptables and handle the rules yourself, but I really hate dealing with iptables&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:3&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. As a stopgap I did hold my nose and add some iptables rules to drop traffic to the &lt;code&gt;tailscale0&lt;/code&gt; interface if it originated from the IP ranges that Docker was configured to use:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 192.168.0.0/16 -o tailscale0 -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 172.17.0.0/12 -o tailscale0 -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;DOCKER-USER&lt;/code&gt; chain is a nice little escape hatch; it comes before the main auto-generated &lt;code&gt;DOCKER&lt;/code&gt; chain, and Docker leaves the rules in it alone.&lt;/p&gt;
&lt;p&gt;So I added these rules, and felt pretty good about myself, and then… everything started breaking in weird ways. After some debugging I realised the problem was DNS&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:4&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;. The server’s DNS resolver is &lt;code&gt;100.100.100.100&lt;/code&gt;, a special Tailscale address. This is so that it can resolve tailnet hostnames via &lt;a href=&#34;https://tailscale.com/kb/1081/magicdns&#34;&gt;MagicDNS&lt;/a&gt; (and so I don’t have to configure my custom DNS servers manually on each device; Tailscale does it for me). My new iptables rules inadvertently dropped all the DNS packets coming from docker containers. D’oh.&lt;/p&gt;
&lt;p&gt;Obviously the solution here is to double down and add MORE iptables rules:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 192.168.0.0/16 -d 100.100.100.100 -o tailscale0 -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 172.17.0.0/12 -d 100.100.100.100 -o tailscale0 -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This got DNS working again, but it all feels a bit gross. Not least because to actually make these persist you need to use &lt;code&gt;iptables-save&lt;/code&gt;, and then you also get all the rules that both Docker and Tailscale have inserted. I came across &lt;a href=&#34;https://github.com/giangi/iptables-docker-filter&#34;&gt;a script&lt;/a&gt; to filter out the Docker ones, but… yuck&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:5&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I realised a cleaner idea might just be to lock down what &lt;code&gt;server&lt;/code&gt; tagged nodes could access within Tailscale itself. That way I can avoid touching iptables at all. It’s handy to be able to &lt;code&gt;curl&lt;/code&gt; services from the host when debugging, but it’s not really necessary. So I removed that access, and… stuff broke again. I’m using my Forgejo instance as a registry for some of the docker images I run, so the docker daemon needs to be able to reach it. I ended up making a new tag for &lt;code&gt;infrastructure&lt;/code&gt;, which can be accessed from &lt;code&gt;server&lt;/code&gt; devices. This does still allow all the docker containers to reach Forgejo, but I already have it set up with appropriate access controls and public/private repository splits. Forgejo is a service designed to run publicly, so this seems a reasonable trade-off for convenience. I used the &lt;code&gt;tests&lt;/code&gt; feature of Tailscale’s ACL config to make sure I’d got the rules right:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tests&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Servers can only access infrastructure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;   &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;proto&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;allow&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:infrastructure:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;deny&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;100.84.16.43:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;me@example.com:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:app:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The whole situation still feels a bit messy. If I ever get around to switching to nftables I might loop back and manually craft some rules for routing traffic, instead of leaving Tailscale and Docker to do their own thing.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr/&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I discovered later on that logging into the container registry at &lt;code&gt;forgejo:3000&lt;/code&gt; actually issued a redirect to &lt;code&gt;https://git.example-net.ts.net/&lt;/code&gt; so this was all basically for naught… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:1&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;I didn’t use Tailscale’s MagicDNS for a long time just because the word “magic” put me off. Only when I eventually got around to learning how it worked, and seeing that it wasn’t really that magical under the hood, did I change my mind. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:2&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;nftables seems far better in lots of ways, but I can’t really be bothered migrating. Maybe next time I reimage the server for whatever reason… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:3&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;It’s always DNS… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:4&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Again, nftables would almost certainly help here. It actually has (gasp) configuration files. But again, I really didn’t want to spend the time migrating. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:5&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
</feed>
