<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Miek Gieben</title>
    <link>https://miek.nl/</link>
    <description>Recent content on Miek Gieben</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <copyright>© Copyright 2007-2024 Miek Gieben</copyright>
    <lastBuildDate>Thu, 14 May 2026 22:04:39 +0200</lastBuildDate>
    <atom:link href="https://miek.nl/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Uncloud Image Pruning</title>
      <link>https://miek.nl/2026/may/14/uncloud-image-pruning/</link>
      <pubDate>Thu, 14 May 2026 22:04:39 +0200</pubDate>
      <guid>https://miek.nl/2026/may/14/uncloud-image-pruning/</guid>
      <description>&lt;p&gt;Currently &lt;code&gt;uc&lt;/code&gt; doesn&amp;rsquo;t have a &lt;em&gt;prune&lt;/em&gt; subcommand to prune images, and even if it had it would still be a&#xA;manual operation. It would be better to automate this. This post shows how.&lt;/p&gt;&#xA;&lt;p&gt;First create an image with this Dockerfile:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;--platform=$BUILDPLATFORM&lt;/span&gt; alpine:latest&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; apk add curl&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; &amp;lt;&amp;lt;EOF&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#/bin/bash&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; ! &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; -S /var/run/docker.sock &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Docker socket /var/run/docker.sock not found&amp;#34;&lt;/span&gt; &amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s -X POST --unix-socket /var/run/docker.sock http://localhost/images/prune&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; true; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sleep 24h&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    curl -s -X POST --unix-socket /var/run/docker.sock http://localhost/images/prune&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt; &amp;gt; /prune&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EOF&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; chmod +x /prune&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WORKDIR /&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CMD&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/prune&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Build and push that image to a registry and then use this Uncloud compose.yaml to deploy:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Uncloud Prometheus</title>
      <link>https://miek.nl/2026/april/26/uncloud-prometheus/</link>
      <pubDate>Sun, 26 Apr 2026 18:22:52 +0200</pubDate>
      <guid>https://miek.nl/2026/april/26/uncloud-prometheus/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/psviderski/uncloud/pull/304&#34;&gt;Prometheus metrics&lt;/a&gt; are being worked on by&#xA;&lt;a href=&#34;https://ratms.nl/projects/uncloud/&#34;&gt;me&lt;/a&gt;, and will hopefully soon be merged in &lt;a href=&#34;https://uncloud.run&#34;&gt;Uncloud&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;uncloudd&lt;/em&gt; metrics endpoint is exposed into the cluster network, so this makes it possible for a&#xA;Prometheus service running inside the cluster to scrape it. For this it just needs to be able to access the API&#xA;to get all machines in the cluster. This can be done by mounting the uncloud socket inside the container, and&#xA;using &lt;code&gt;uc&lt;/code&gt; with &lt;a href=&#34;https://github.com/psviderski/uncloud/issues/335&#34;&gt;structured output&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Uncloud L4</title>
      <link>https://miek.nl/2026/april/25/uncloud-l4/</link>
      <pubDate>Sat, 25 Apr 2026 13:21:52 +0200</pubDate>
      <guid>https://miek.nl/2026/april/25/uncloud-l4/</guid>
      <description>&lt;p&gt;Natively &lt;a href=&#34;https://uncloud.run&#34;&gt;Uncloud&lt;/a&gt; doesn&amp;rsquo;t do L4 forwarding. This is an &lt;a href=&#34;https://github.com/psviderski/uncloud/issues/108&#34;&gt;open&#xA;issue&lt;/a&gt; as we are figuring out how to actually do this. But&#xA;it turns out you can already do this with the current code - well almost.&lt;/p&gt;&#xA;&lt;p&gt;Buckle up, because there is quite some stuff you may need:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;A patched Uncloud, see &lt;a href=&#34;https://github.com/psviderski/uncloud/pull/358&#34;&gt;this PR&lt;/a&gt; for that.&lt;/li&gt;&#xA;&lt;li&gt;A custom &lt;a href=&#34;https://caddyserver.com&#34;&gt;Caddy&lt;/a&gt; build, with the &lt;a href=&#34;https://github.com/mholt/caddy-l4&#34;&gt;L4&lt;/a&gt; plugin.&lt;/li&gt;&#xA;&lt;li&gt;A DNS server, I use &lt;a href=&#34;https://atomdns.miek.nl&#34;&gt;atomdns&lt;/a&gt; of course.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Note I use a fork + merge requests I need that is available at: &lt;a href=&#34;https://github.com/miekg/uncloudplus&#34;&gt;https://github.com/miekg/uncloudplus&lt;/a&gt; .&lt;/p&gt;</description>
    </item>
    <item>
      <title>Uncloud Private Registries</title>
      <link>https://miek.nl/2026/april/14/uncloud-private-registries/</link>
      <pubDate>Tue, 14 Apr 2026 19:31:00 +0200</pubDate>
      <guid>https://miek.nl/2026/april/14/uncloud-private-registries/</guid>
      <description>&lt;p&gt;While pushing &lt;a href=&#34;https://github.com/psviderski/uncloud/pull/306&#34;&gt;this PR&lt;/a&gt;, the answer was that this &lt;em&gt;was already&#xA;working&lt;/em&gt;! But kind of unintuitive, but smart as it re-uses whatever docker setup you got (i.e. credentials&#xA;helpers).&lt;/p&gt;&#xA;&lt;p&gt;So to get this working you:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% docker login registry.science.ru.nl&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Username: bla&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Password:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then use &lt;code&gt;uc deploy -f .../compose.yml&lt;/code&gt; just like you did before. Now it should pull from the private repo&#xA;and things &amp;ldquo;just work&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;See &lt;a href=&#34;https://uncloud.run/docs/guides/deployments/deploy-app/#pull-from-a-private-registry&#34;&gt;this guide&lt;/a&gt; for&#xA;canonical text on this.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testscript highlighting in Neovim</title>
      <link>https://miek.nl/2026/april/09/testscript-highlighting-in-neovim/</link>
      <pubDate>Thu, 09 Apr 2026 20:38:06 +0200</pubDate>
      <guid>https://miek.nl/2026/april/09/testscript-highlighting-in-neovim/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://blog.windpul.eu/posts/testscript/&#34;&gt;This is a good article&lt;/a&gt; on how to use &lt;em&gt;testscript&lt;/em&gt; in Go(lang). It&#xA;also goes as far as &lt;a href=&#34;https://blog.windpul.eu/posts/testscript/#bonus-neovim-syntax-highlighting&#34;&gt;adding a syntax&#xA;file&lt;/a&gt;. But I&amp;rsquo;m 100% into Neovim,&#xA;so this needs to be tree-sitter grammar on my system.&lt;/p&gt;&#xA;&lt;p&gt;Well&amp;hellip; this was a journey and I needed claude.ai for a lot of stuff to pull it off.&#xA;I &lt;em&gt;also&lt;/em&gt; wanted to insert Go syntax highlighting for Go blocks, like in this file.&lt;/p&gt;&#xA;&lt;p&gt;This is working on Fedora 43 and Ubuntu 26.04 and depends on a up-to-date &lt;code&gt;tree-sitter-cli&lt;/code&gt; as this is the&#xA;main way of generating the parser.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Uncloud</title>
      <link>https://miek.nl/2026/march/16/uncloud/</link>
      <pubDate>Mon, 16 Mar 2026 14:00:40 +0100</pubDate>
      <guid>https://miek.nl/2026/march/16/uncloud/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m playing with &lt;a href=&#34;https://uncloud.run&#34;&gt;Uncloud&lt;/a&gt; to see if it is something we can use at $WORK. Pretty&#xA;impressed with it already, as I&amp;rsquo;ve written something worse &lt;a href=&#34;https://github.com/miekg/pgo&#34;&gt;pgo&lt;/a&gt;, that was&#xA;(obviously) not good enough. Uncloud does: implement a subset of the Docker(-compose) API, uses gRPC and&#xA;wireguard to create mini network; just brilliant. Haven&amp;rsquo;t seen prometheus metrics yet, although Caddy is used&#xA;for the proxy, but more prometheus metrics would make sense. (Which you can then observe through a cluster&#xA;hosted prometheus&amp;hellip;?)&lt;/p&gt;</description>
    </item>
    <item>
      <title>Forgejo Go Benchstat</title>
      <link>https://miek.nl/2026/january/30/forgejo-go-benchstat/</link>
      <pubDate>Fri, 30 Jan 2026 17:53:04 +0100</pubDate>
      <guid>https://miek.nl/2026/january/30/forgejo-go-benchstat/</guid>
      <description>&lt;p&gt;For the longest time I wanted to see the performance impact of my changes. This desire goes back years, back&#xA;to the early days of &lt;a href=&#34;https://miek.nl/2016/march/18/announcing-coredns/&#34;&gt;CoreDNS&lt;/a&gt;. And now I finally have it.&lt;/p&gt;&#xA;&lt;p&gt;It does require running your own forgejo-runner on your own hardware to have any meaningful data. Without&#xA;further adu:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# On https://codeberg.org/miekg/dns/actions you can see the run and copy and paste a new.txt if performance is&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# better. Put this contents in old.txt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;push, pull_request]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;test&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;atoom-tiny&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-go@v6&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;go-version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ vars.GOVERSION }}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apt-get update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          apt-get -y install dnsperf jq&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          go install golang.org/x/perf/cmd/benchstat@latest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          (cd cmd/reflect; go build)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          HOSTNAME=atoom-tiny&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          # Sleep here so we have the machine to ourselves.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          sleep 60&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          (cd cmd/reflect; make new.txt)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          REF=$(echo ${{ forgejo.ref }} | cut -d/ -f3)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          echo ${{ forgejo.api_url}}/repos/${{ forgejo.repository }}/issues/${REF}/comments&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          echo &amp;#34;{\&amp;#34;body\&amp;#34;: $(cd cmd/reflect; make stat | jq -sR .)}&amp;#34; | \&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          curl --json @- \&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          -H &amp;#39;Authorization: token ${{ forgejo.token }}&amp;#39; \&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                          ${{ forgejo.api_url}}/repos/${{ forgejo.repository }}/issues/${REF}/comments&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See &lt;a href=&#34;https://codeberg.org/miekg/dns&#34;&gt;https://codeberg.org/miekg/dns&lt;/a&gt; for all other bits that are needed.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Create a Pull Request from Git in Forgejo</title>
      <link>https://miek.nl/2026/january/28/create-a-pull-request-from-git-in-forgejo/</link>
      <pubDate>Wed, 28 Jan 2026 06:50:48 +0100</pubDate>
      <guid>https://miek.nl/2026/january/28/create-a-pull-request-from-git-in-forgejo/</guid>
      <description>&lt;p&gt;Recently I&amp;rsquo;ve started to move all my project to &lt;a href=&#34;https://codeberg.org/miekg&#34;&gt;Codeberg&lt;/a&gt;. This is working great,&#xA;but one of the things I really missed where the git-push options from GitLab where you can create a PR just by&#xA;pushing a branch upstream.&lt;/p&gt;&#xA;&lt;p&gt;Thanks to my whining about this on Mastodon I got &lt;a href=&#34;https://infosec.exchange/@x_cli/115967604917936736&#34;&gt;this&#xA;reply&lt;/a&gt; about an&#xA;&lt;a href=&#34;https://github.com/maxking/forgejo-create-pr&#34;&gt;create-pr-action&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Well, putting this all together, I right now have this script (with little, or no error checking) that does the&#xA;heavy lifting of creating a PR using Forgejo&amp;rsquo;s API. This needs an API token with read/write rights on your&#xA;repo (and only that):&lt;/p&gt;</description>
    </item>
    <item>
      <title>2025 Fotos 0xf7.8 feest</title>
      <link>https://miek.nl/galleries/2025-0x7f/</link>
      <pubDate>Sat, 01 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2025-0x7f/</guid>
      <description>&lt;p&gt;De fotos van het &lt;a href=&#34;https://0x7f.8.miek.nl&#34;&gt;0x7f.8 feest&lt;/a&gt; op 1 november 2025 in Groenewoud met al onze vrienden.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Groesbeek&#39;s Gruwelijkste 2025</title>
      <link>https://miek.nl/galleries/2025-groesbeeks-gruwelijkste/</link>
      <pubDate>Sun, 21 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2025-groesbeeks-gruwelijkste/</guid>
      <description>&lt;p&gt;Op zondag 21 September Groesbeek&amp;rsquo;s Gruwelijkste (11e editie, de &lt;em&gt;laatste&lt;/em&gt;) gereden. De 75 km.&lt;/p&gt;</description>
    </item>
    <item>
      <title>PAM unixsock</title>
      <link>https://miek.nl/2025/march/14/pam-unixsock/</link>
      <pubDate>Fri, 14 Mar 2025 12:14:47 +0100</pubDate>
      <guid>https://miek.nl/2025/march/14/pam-unixsock/</guid>
      <description>&lt;p&gt;Ever felt the need to do something with PAM, like implementing 2FA in SSH? You are left with a few&#xA;bad choices, among others you&amp;rsquo;ll need to write something (complex) in C. I rather not do that, so&#xA;I&amp;rsquo;ve created &lt;a href=&#34;https://github.com/miekg/pam-unixsock&#34;&gt;pam-unixsock&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This is &lt;em&gt;tiny&lt;/em&gt;, the most trouble I had with concatenating strings with a space in between,&#xA;because, you know, C. Anyway &lt;em&gt;tiny&lt;/em&gt;. It doesn&amp;rsquo;t do much and gets you into another language quickly!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Format Go HTML templates</title>
      <link>https://miek.nl/2025/february/19/format-go-html-templates/</link>
      <pubDate>Wed, 19 Feb 2025 15:20:33 +0100</pubDate>
      <guid>https://miek.nl/2025/february/19/format-go-html-templates/</guid>
      <description>&lt;p&gt;Because I was fed up with the lack of options (none), I write a tool that&#xA;can format Go HTML templates: you can find it &lt;a href=&#34;https://github.com/miekg/gotmplfmt&#34;&gt;here&lt;/a&gt;. Includes&#xA;screenshots!&lt;/p&gt;&#xA;&lt;p&gt;Formatting Go &lt;em&gt;text&lt;/em&gt; templates is pure madness, but the above code works well on HTML templates. If&#xA;have find issues or need more functionality open a PR against the repo.&lt;/p&gt;&#xA;&lt;p&gt;Have this in neovim:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;au&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;FileType&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gohtmltmpl&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;command&lt;/span&gt;! &lt;span style=&#34;color:#a6e22e&#34;&gt;Fmt&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;silent&lt;/span&gt; %!&lt;span style=&#34;color:#a6e22e&#34;&gt;gotmplfmt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;au&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;FileType&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gohtmltmpl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &amp;amp;&lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;formatprg&lt;/span&gt;=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gotmplfmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;update-2025-05-31&#34;&gt;Update 2025-05-31&lt;/h2&gt;&#xA;&lt;p&gt;In my new neovim setup (with conform.lua) I have this:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Matchup in Neovim for Go templates</title>
      <link>https://miek.nl/2024/december/07/matchup-in-neovim-for-go-templates/</link>
      <pubDate>Sat, 07 Dec 2024 12:04:24 +0100</pubDate>
      <guid>https://miek.nl/2024/december/07/matchup-in-neovim-for-go-templates/</guid>
      <description>&lt;p&gt;After dealing with &lt;a href=&#34;https://pkg.go.dev/text/template&#34;&gt;Go templates&lt;/a&gt; (also HTML templates) for more&#xA;than a year and keep loosing track of where each block &lt;code&gt;{{end}}s&lt;/code&gt; I finally &lt;a href=&#34;https://mastodon.cloud/@miek/113606613003828116&#34;&gt;did something about&#xA;it&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;But that didn&amp;rsquo;t work that good. So I&amp;rsquo;ve switch to the&#xA;&lt;a href=&#34;https://github.com/andymass/vim-matchup&#34;&gt;match-up&lt;/a&gt; plugin, which is better than the built-in&#xA;&lt;code&gt;matchit&lt;/code&gt; that I was using previously. With Neovim I&amp;rsquo;m using this setup:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Plug&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;andymass/vim-matchup&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this extra bit of config:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;require&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;nvim-treesitter.configs&amp;#39;&lt;/span&gt;.setup {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  matchup &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    enable &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This in itself does not make template matching work, for this I just copied the&#xA;&lt;a href=&#34;https://github.com/andymass/vim-matchup/wiki/The-match-up-wiki#hugo&#34;&gt;Hugo template matcher&lt;/a&gt;&#xA;(which is just like Go templating) to the correct place. Doing this with &lt;em&gt;some&lt;/em&gt; automation from&#xA;inside Neovim:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kong Go CLI manual pages</title>
      <link>https://miek.nl/2024/november/08/kong-go-cli-manual-pages/</link>
      <pubDate>Fri, 08 Nov 2024 11:38:55 +0100</pubDate>
      <guid>https://miek.nl/2024/november/08/kong-go-cli-manual-pages/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m using &lt;a href=&#34;https://github.com/alecthomas/kong&#34;&gt;Kong the CLI argument parser&lt;/a&gt; to create manual pages&#xA;from the arguments and help described in the Kong structure that tells your CLI how to parse its command&#xA;line.&lt;/p&gt;&#xA;&lt;p&gt;With a lot of use from the &lt;code&gt;reflect&lt;/code&gt; package (this was before I discovered kong actually has an API&#xA;you can use), I&amp;rsquo;m creating manual pages from the kong CLI definition, while having great fun with&#xA;parsing &lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt; and other tags to make the manual page really readable.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kong Go CLI</title>
      <link>https://miek.nl/2024/november/01/kong-go-cli/</link>
      <pubDate>Fri, 01 Nov 2024 11:38:55 +0100</pubDate>
      <guid>https://miek.nl/2024/november/01/kong-go-cli/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m a fan of &lt;a href=&#34;https://github.com/alecthomas/kong&#34;&gt;Kong the CLI argument parser&lt;/a&gt;, I use it to&#xA;automatically create manual pages, (bash) completion and do a lot of validation inside it. (This guy&#xA;also has other really interesting packages, and he&amp;rsquo;s a huge fan of Go&amp;rsquo;s struct tags).&lt;/p&gt;&#xA;&lt;p&gt;I wanted to do validation inside Kong as well, for this Kong has&#xA;&lt;a href=&#34;https://github.com/alecthomas/kong?tab=readme-ov-file#validation&#34;&gt;validation&lt;/a&gt;, which is just a&#xA;method (&lt;code&gt;Validate() error&lt;/code&gt;) on a type. Now most types I have are just &lt;code&gt;string&lt;/code&gt; or any other builtin&#xA;type. For validation to work, all these types must be re-typed to another type on which the method&#xA;can be applied, which is annoying. I wanted a better way&amp;hellip;&lt;/p&gt;</description>
    </item>
    <item>
      <title>eBPF from Go - IV - Code generation</title>
      <link>https://miek.nl/2024/october/28/ebpf-from-go-iv-code-generation/</link>
      <pubDate>Mon, 28 Oct 2024 15:47:08 +0200</pubDate>
      <guid>https://miek.nl/2024/october/28/ebpf-from-go-iv-code-generation/</guid>
      <description>&lt;p&gt;Played more with TinyGo, but it always generates code for (minimal) reflection - i.e. the &lt;code&gt;reflect&lt;/code&gt;&#xA;package, because it requires that for its &lt;code&gt;map&lt;/code&gt; implementation. I could skip or not generate that,&#xA;but then that would mean using a map would be &amp;hellip; weird? Anyhow it looked that even TinyGo does too&#xA;much for eBPF. So plan D: generate eBPF code (and Go code) using Go. Cilium has done a lot of work&#xA;in this regard.&lt;/p&gt;</description>
    </item>
    <item>
      <title>eBPF from Go - III - Reducing the SSA</title>
      <link>https://miek.nl/2024/september/30/ebpf-from-go-iii-reducing-the-ssa/</link>
      <pubDate>Mon, 30 Sep 2024 15:47:08 +0200</pubDate>
      <guid>https://miek.nl/2024/september/30/ebpf-from-go-iii-reducing-the-ssa/</guid>
      <description>&lt;p&gt;Again some progress. I&amp;rsquo;m mostly focussing on removing code from the SSA representation&#xA;(&lt;code&gt;-internal-dumpssa&lt;/code&gt;), so that I can work with a clean slate. As BPF is so limited almost none of&#xA;the features from Go make sense, although in some far fetched future it would be super cool to have&#xA;channels and goroutines to something in BPF - but not today. First need to get to &amp;ldquo;Hello World&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m building this code:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Groesbeek&#39;s Gruwelijkste 2024</title>
      <link>https://miek.nl/galleries/2024-groesbeeks-gruwelijkste/</link>
      <pubDate>Sun, 15 Sep 2024 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2024-groesbeeks-gruwelijkste/</guid>
      <description>&lt;p&gt;Op zondag 15 September Groesbeek&amp;rsquo;s Gruwelijkste (10e editie) gereden. De 75 km.&lt;/p&gt;</description>
    </item>
    <item>
      <title>eBPF from Go - II</title>
      <link>https://miek.nl/2024/august/30/ebpf-from-go-ii/</link>
      <pubDate>Fri, 30 Aug 2024 15:47:08 +0200</pubDate>
      <guid>https://miek.nl/2024/august/30/ebpf-from-go-ii/</guid>
      <description>&lt;p&gt;Following up from the previous blog post&amp;hellip; I&amp;rsquo;ve got a JSON file with the string &amp;lsquo;bpf&amp;rsquo; in the&#xA;correct place. Let&amp;rsquo;s see what tinygo thinks of that:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;% ./build/tinygo build -o miekg/main.bpf -target bpf ./miekg/main.go&#xA;No available targets are compatible with triple &amp;quot;bpf-unknown-unknown&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;clang&lt;/code&gt; indeed does not list bpf as a valid target, so this needs to be added.&lt;/p&gt;&#xA;&lt;p&gt;The llvm build is configured from the main&#xA;&lt;a href=&#34;https://github.com/tinygo-org/tinygo/blob/release/GNUmakefile&#34;&gt;GNUMakefile&lt;/a&gt;, with&#xA;&lt;code&gt;-DLLVM_TARGETS_TO_BUILD...&lt;/code&gt;. Using grep and find I found the &amp;ldquo;llvm/test/CodeGen&amp;rdquo; directory, which,&#xA;in addition to all listed targets also has a BPF directory. Let&amp;rsquo;s add BPF to that list and recompile.&lt;/p&gt;</description>
    </item>
    <item>
      <title>eBPF from Go; First Steps</title>
      <link>https://miek.nl/2024/august/29/ebpf-from-go-first-steps/</link>
      <pubDate>Thu, 29 Aug 2024 20:04:35 +0200</pubDate>
      <guid>https://miek.nl/2024/august/29/ebpf-from-go-first-steps/</guid>
      <description>&lt;p&gt;So I had this itch that I wanted to make a Go program compile to eBPF and be able to load that&#xA;program in the Linux kernel by use of &lt;code&gt;bpftool&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;As I &lt;a href=&#34;https://github.com/miekg/ebpf/blob/main/README.md&#34;&gt;say in github.com/miekg/ebpf&lt;/a&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;eBPF in C? What am I, a farmer?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;After much reading about eBPF and thinking about how that would work from Go, I figured that would&#xA;involve writing a Go compiler.&lt;/p&gt;&#xA;&lt;p&gt;So I could:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;hack the official Go compiler and (try to) add a eBPF target (which would probably never&#xA;be added as an official target because of all the constraints eBPF has).&lt;/p&gt;</description>
    </item>
    <item>
      <title>eBPF in Go</title>
      <link>https://miek.nl/2024/august/22/ebpf-in-go/</link>
      <pubDate>Thu, 22 Aug 2024 18:46:57 +0200</pubDate>
      <guid>https://miek.nl/2024/august/22/ebpf-in-go/</guid>
      <description>&lt;p&gt;What if I could program eBPF in &lt;em&gt;pure&lt;/em&gt; Go? I want to use eBPF and lots of current tooling exist, but&#xA;I like Go. I don&amp;rsquo;t want to use clang to create the ELF binary that then gets loaded into the Linux&#xA;kernel. I want to use Go to create that ELF file. The heavy lifting of loading and&#xA;inspecting can be done via bpftool (although I&amp;rsquo;m aware that Go programs exist that do this), but&#xA;bpftool looks like the standard way of interacting with the kernel&amp;rsquo;s eBPF subsystem.&lt;/p&gt;</description>
    </item>
    <item>
      <title>De Haan 2024</title>
      <link>https://miek.nl/galleries/2024-de-haan/</link>
      <pubDate>Thu, 08 Aug 2024 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2024-de-haan/</guid>
      <description>&lt;p&gt;Vakantie in het Belgische De Haan samen met Toni.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rügen 2024</title>
      <link>https://miek.nl/galleries/2024-rugen/</link>
      <pubDate>Fri, 02 Aug 2024 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2024-rugen/</guid>
      <description>&lt;p&gt;Twee weken vakantie in het Duitse Rügen.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Charlie 2024</title>
      <link>https://miek.nl/galleries/2024-charlie/</link>
      <pubDate>Wed, 22 May 2024 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2024-charlie/</guid>
      <description>&lt;p&gt;12e verjaardag van Charlie.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Center Parcs 2024</title>
      <link>https://miek.nl/galleries/2024-centerparcs/</link>
      <pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2024-centerparcs/</guid>
      <description>&lt;p&gt;Met Inbal en Yaniv naar Center Parcs in Zandvoort.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Printing from Android </title>
      <link>https://miek.nl/2024/february/24/printing-from-android/</link>
      <pubDate>Sat, 24 Feb 2024 20:03:54 +0100</pubDate>
      <guid>https://miek.nl/2024/february/24/printing-from-android/</guid>
      <description>&lt;p&gt;Quick note to self.&lt;/p&gt;&#xA;&lt;p&gt;Printing from Android &lt;em&gt;requires&lt;/em&gt; IPP. If your printing does not support this protocol out of the box&#xA;you will not be able to directly print from Android devices.&lt;/p&gt;&#xA;&lt;p&gt;CUPS can then be used to translate between IPP and JetDirect (in my case). Install and configure&#xA;CUPS and then on Android configure the printer. The later means connecting to a printer &lt;em&gt;by IP&#xA;address&lt;/em&gt;. In that form enter the following:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Config Management, part III: Rolling Back</title>
      <link>https://miek.nl/2024/february/02/config-management-part-iii-rolling-back/</link>
      <pubDate>Fri, 02 Feb 2024 15:20:33 +0100</pubDate>
      <guid>https://miek.nl/2024/february/02/config-management-part-iii-rolling-back/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://miek.nl/2024/february/01/config-management-part-ii-microcode-language/&#34;&gt;The second part&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In the previous part we looked how a micro language would look like, now I want to focus on what it&#xA;means to roll back to a previous version. First take a look at an instruction that have no obvious&#xA;reverse: CHMOD&lt;/p&gt;&#xA;&lt;p&gt;When rolling back CHMOD you want to revert to the previous permissions. This would work&#xA;automatically &lt;em&gt;if&lt;/em&gt; there was an older CHMOD that would also set the permission, but in a lot of&#xA;situations you probably just go with the (package) defaults. This implies you don&amp;rsquo;t know what a&#xA;CHMOD reversal would be, and that implies we need to track that, like in a proper &lt;em&gt;journal&lt;/em&gt;. As said&#xA;each instruction has an implicit condition, if that condition doesn&amp;rsquo;t hold, it executes the&#xA;instruction, we can utilize that state and save it in the journal. Let&amp;rsquo;s see in detail how this&#xA;would work with something like CHMOD.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Config Management, part II: Microcode Language</title>
      <link>https://miek.nl/2024/february/01/config-management-part-ii-microcode-language/</link>
      <pubDate>Thu, 01 Feb 2024 15:20:33 +0100</pubDate>
      <guid>https://miek.nl/2024/february/01/config-management-part-ii-microcode-language/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://miek.nl/2024/january/29/config-management/&#34;&gt;The first part&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This cfg mgmt system uses a micro language to perform the changes on the target&#xA;system. This language is limited in its scope and has the following &amp;ldquo;instructions&amp;rdquo;:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;INSTRUCTION&lt;/th&gt;&#xA;          &lt;th&gt;ARITY&lt;/th&gt;&#xA;          &lt;th&gt;ARGUMENTS&lt;/th&gt;&#xA;          &lt;th&gt;REMARK&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;REM&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;TEXT&lt;/td&gt;&#xA;          &lt;td&gt;a comment&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;MKDIR&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;MODE PATH&lt;/td&gt;&#xA;          &lt;td&gt;create a directory&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;COPY&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;SRC-PATH DST-PATH&lt;/td&gt;&#xA;          &lt;td&gt;copy a file&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;CHMOD&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;MODE PATH&lt;/td&gt;&#xA;          &lt;td&gt;set the mode&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;CHOWN&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;USER/ID PATH&lt;/td&gt;&#xA;          &lt;td&gt;set the owner&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;CHGRP&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;GROUP/ID PATH&lt;/td&gt;&#xA;          &lt;td&gt;set the group&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;RM&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;PATH&lt;/td&gt;&#xA;          &lt;td&gt;rm the file&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;EXEC&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;CMD&lt;/td&gt;&#xA;          &lt;td&gt;install a package&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;These micro-instruction basically all call a simple system call to make the changes.&#xA;Note, except for the latter this is the Unix API of everything is a file. &lt;code&gt;EXEC&lt;/code&gt; is now only used&#xA;to install/deinstall a package; of course such a generic instruction is ripe for abuse&amp;hellip;&lt;/p&gt;</description>
    </item>
    <item>
      <title>OSC52: My Cut &amp; Paste Journey</title>
      <link>https://miek.nl/2024/january/31/osc52-my-cut-paste-journey/</link>
      <pubDate>Wed, 31 Jan 2024 11:03:41 +0000</pubDate>
      <guid>https://miek.nl/2024/january/31/osc52-my-cut-paste-journey/</guid>
      <description>&lt;p&gt;In the olden days with X11, you could just do x11-forwarding in SSH and remote cut and paste would&#xA;work. Now with Wayland, this is all broken and supposedly &amp;ldquo;there are better ways of doing it&amp;rdquo;. One&#xA;of those is&#xA;&lt;a href=&#34;https://www.reddit.com/r/vim/comments/k1ydpn/a_guide_on_how_to_copy_text_from_anywhere/&#34;&gt;OSC52&lt;/a&gt;&#xA;support in terminals, but not in &lt;a href=&#34;https://wiki.gnome.org/Apps/Terminal/VTE&#34;&gt;VTE&lt;/a&gt; based ones, like&#xA;&lt;a href=&#34;https://gnunn1.github.io/tilix-web/&#34;&gt;Tilix&lt;/a&gt;, which &lt;strike&gt;is&lt;/strike&gt; was my default terminal.&#xA;(See &lt;a href=&#34;https://gitlab.gnome.org/GNOME/vte/-/issues/2495&#34;&gt;https://gitlab.gnome.org/GNOME/vte/-/issues/2495&lt;/a&gt; for the 5(!) year old bug).&lt;/p&gt;&#xA;&lt;p&gt;So I wanted this to work, which meant changing terminal and configuring Neovim - where the latter&#xA;was way more complex, hard to debug and reason about.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Config Management</title>
      <link>https://miek.nl/2024/january/29/config-management/</link>
      <pubDate>Mon, 29 Jan 2024 14:20:33 +0100</pubDate>
      <guid>https://miek.nl/2024/january/29/config-management/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;this project needs a name and a domain.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;After many years of playing with YAML in k8s, I&amp;rsquo;ve returned to using CFEngine (at work). The last&#xA;config management software before that was Puppet. An issue I see with all modern config management&#xA;tooling is the lack of monitoring and the impossibility to cleanly roll back. In k8s it works&#xA;better, but that&amp;rsquo;s only for pods running in k8s (which are stateless), not the underlying machines.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Graaf</title>
      <link>https://miek.nl/2023/december/28/graaf/</link>
      <pubDate>Thu, 28 Dec 2023 18:11:35 +0100</pubDate>
      <guid>https://miek.nl/2023/december/28/graaf/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://gitlab.science.ru.nl/cncz/go/-/blob/main/cmd/graaf/&#34;&gt;Graaf&lt;/a&gt; is a Go program that translates&#xA;simple dashboards written in YAML to Grafana JSON. It has an extensive &lt;a href=&#34;https://gitlab.science.ru.nl/cncz/go/-/blob/main/cmd/graaf/graaf.1&#34;&gt;manual&#xA;page&lt;/a&gt; that explains its usage.&#xA;This is also known as Grafana as code, but then for real.&lt;/p&gt;&#xA;&lt;p&gt;The following is a dashboard with 4 panels that I use for my own monitoring.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Overview i&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;uid&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;dashboard-overview&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;panels&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;timeseries&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Network Bytes [5m] - edgemax.i&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;y&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Bps&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;exprs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rate(ifHCOutOctets{ifAlias=&amp;#34;eth0&amp;#34;,job=&amp;#34;edgemax&amp;#34;}[5m])&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{ifAlias}} transmit&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rate(ifHCInOctets{ifAlias=&amp;#34;eth0&amp;#34;,job=&amp;#34;edgemax&amp;#34;}[5m])&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{ifAlias}} receive&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;negative-y&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;timeseries&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;HTTPS Queries [5m]&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;y&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rps&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;exprs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sum by (host) (rate(caddy_http_request_count_total{job=&amp;#34;caddy&amp;#34;}[5m]))&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{host}}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sum (rate(caddy_http_request_count_total{job=&amp;#34;caddy&amp;#34;}[5m]))&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;total&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;negative-y&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;timeseries&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;DNS Queries [5m]&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;y&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rps&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;exprs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sum by (zone) (rate(coredns_dns_requests_total{job=&amp;#34;nsdns&amp;#34;,zone!=&amp;#34;dropped&amp;#34;}[5m]))&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{zone}}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sum (rate(coredns_dns_requests_total{job=&amp;#34;nsdns&amp;#34;}[5m]))&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;total&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;negative-y&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sum (rate(coredns_dns_requests_total{job=&amp;#34;nsdns&amp;#34;,zone=&amp;#34;dropped&amp;#34;}[5m]))&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;dropped&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;negative-y&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;timeseries&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Network Bytes [5m] - nuc.i&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;y&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;unit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Bps&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;exprs&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rate(node_network_transmit_bytes_total{job=&amp;#34;node&amp;#34;,device=&amp;#34;eno1&amp;#34;}[5m])&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{device}} transmit&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;threshold&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ok{value=&amp;#34;0&amp;#34;}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;expr&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rate(node_network_receive_bytes_total{job=&amp;#34;node&amp;#34;,device=&amp;#34;eno1&amp;#34;}[5m])&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;legend&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{{device}} receive&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;negative-y&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This dashboard is 47 lines, the generated JSON dashboard is 500 lines, a ~10-fold reduction in&#xA;cruft. Not bad!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Gallery Shortcode</title>
      <link>https://miek.nl/2023/november/21/gallery-shortcode/</link>
      <pubDate>Tue, 21 Nov 2023 16:27:45 +0100</pubDate>
      <guid>https://miek.nl/2023/november/21/gallery-shortcode/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m using the following shortcode (saved as &lt;code&gt;gallery.html&lt;/code&gt;) in Hugo to generate a gallery containing&#xA;both video and photos. Comments in the code.&lt;/p&gt;&#xA;&lt;p&gt;May it be helpful for you. It comes (of course) with no support. The cover photo handling is done by&#xA;my Hugo theme (terminal) btw.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-go-tmpl&#34; data-lang=&#34;go-tmpl&#34;&gt;&amp;lt;!--&#xA;    All img/*.{webm,ogv} video files are taken and simularly the caption file is used&#xA;    to generate a video control.&#xA;--&amp;gt;&#xA;&#xA;{{- $videos := .Page.Resources.Match &amp;#34;img/*.webm&amp;#34; -}}&#xA;{{- $videos = $videos | append ( .Page.Resources.Match &amp;#34;img/*.ogv&amp;#34; ) -}}&#xA;{{- range $videos -}}&#xA;    {{- $caption := &amp;#34;&amp;#34; -}}&#xA;    {{- $captionfile :=  printf &amp;#34;%s.%s&amp;#34; ( strings.TrimSuffix (path.Ext .RelPermalink) .RelPermalink ) &amp;#34;txt&amp;#34; -}}&#xA;    {{- if os.FileExists $captionfile -}}&#xA;        {{ $caption = os.ReadFile $captionfile | markdownify -}}&#xA;    {{- end -}}&#xA;    {{- $type := printf &amp;#34;%s/%s&amp;#34; &amp;#34;video&amp;#34; (slicestr (path.Ext .RelPermalink) 1) -}}&#xA;    {{- $type = replace $type &amp;#34;ogv&amp;#34; &amp;#34;ogg&amp;#34; -}}&#xA;    &amp;lt;figure&amp;gt;&#xA;    &amp;lt;video controls preload=&amp;#34;auto&amp;#34; width=&amp;#34;100%&amp;#34; playsinline class=&amp;#34;html-video&amp;#34;&amp;gt;&#xA;        &amp;lt;source src=&amp;#34;{{ .RelPermalink }}&amp;#34; type=&amp;#34;{{ $type }}&amp;#34;&amp;gt;&#xA;    &amp;lt;/video&amp;gt;&#xA;    {{- if $caption -}}&#xA;        &amp;lt;figcaption&amp;gt;&#xA;            &amp;lt;p&amp;gt;{{ $caption }}&amp;lt;/p&amp;gt;&#xA;        &amp;lt;/figcaption&amp;gt;&#xA;    {{- end -}}&#xA;    &amp;lt;/figure&amp;gt;&#xA;{{ end }}&#xA;&#xA;&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.1/css/lightbox.min.css&amp;#34; integrity=&amp;#34;sha256-tBxlolRHP9uMsEFKVk+hk//ekOlXOixLKvye5W2WR5c=&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34; /&amp;gt;&#xA;&amp;lt;script src=&amp;#34;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js&amp;#34; integrity=&amp;#34;sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&#xA;&amp;lt;script src=&amp;#34;https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.1/js/lightbox.min.js&amp;#34; integrity=&amp;#34;sha256-CtKylYan+AJuoH8jrMht1+1PMhMqrKnB8K5g012WN5I=&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&#xA;&#xA;&amp;lt;!--&#xA;    The galleries must be all lowercase otherwise the caption are not found.&#xA;    We use a flexport to show 3 photos in a row, and that should work in mobile as well.&#xA;    Thumbs are generated on the fly.&#xA;&#xA;    Each gallery is placed under a content/galleries as:&#xA;&#xA;        content/galleries/album1&#xA;            /index.md - normal index stuff, with the &amp;#39;gallery &amp;#39;short code in it.&#xA;            img/      - symlink to all photos (and captions)&#xA;            cover.jpg -&amp;gt; img/cover.jpg  - if exist, this will be used as the cover image.&#xA;            video.webm -&amp;gt; see snippet above&#xA;&#xA;    In the photo directory a .txt file with the same basename as the photo is used as&#xA;    a caption. This is in markdown format. The cover.jpg (or whatever extension) is skipped&#xA;    when generating the gallery.&#xA;&#xA;    Clicking used the lightbox JS to show a slideshow like thing - I may selfhost the javascript&#xA;    at some point.&#xA;--&amp;gt;&#xA;&#xA;{{ $image := (.Page.Resources.ByType &amp;#34;image&amp;#34;) }}&#xA;{{ $i := 0 }}&#xA;{{ with $image }}&#xA;    {{ range . }}&#xA;    {{ if not ( hasPrefix .Name &amp;#34;cover.&amp;#34; ) }}&#xA;        {{ if not ( hasPrefix .Name &amp;#34;img/cover.&amp;#34; ) }}&#xA;            {{ if eq (mod $i 3) 0 }}&#xA;                &amp;lt;div class=&amp;#34;flex-container&amp;#34;&amp;gt;&#xA;            {{ end }}&#xA;            {{ $resized := .Fill &amp;#34;300x230 q70&amp;#34; }}&#xA;            {{ $caption := &amp;#34;&amp;#34; }}&#xA;            {{ $captionfile :=  printf &amp;#34;%s.%s&amp;#34; ( strings.TrimSuffix (path.Ext .RelPermalink) .RelPermalink ) &amp;#34;txt&amp;#34; }}&#xA;            {{ if os.FileExists $captionfile }}&#xA;                {{ $caption = os.ReadFile $captionfile | markdownify }}&#xA;            {{ end }}&#xA;            &amp;lt;div style=&amp;#34;width:{{ $resized.Width }}px&amp;#34;&amp;gt;&#xA;                &amp;lt;figure&amp;gt;&#xA;                    &amp;lt;a href=&amp;#34;{{ .Permalink }}&amp;#34; data-lightbox=&amp;#34;x&amp;#34; data-title=&amp;#34;{{ $caption }}&amp;#34;&amp;gt;&#xA;                    &amp;lt;img loading=&amp;#34;lazy&amp;#34; src=&amp;#34;{{ $resized.Permalink }}&amp;#34; /&amp;gt;&#xA;                &amp;lt;/a&amp;gt;&#xA;                {{ if $caption }}&#xA;                  &amp;lt;figcaption&amp;gt;&#xA;                    &amp;lt;p&amp;gt;{{ $caption }}&amp;lt;/p&amp;gt;&#xA;                  &amp;lt;/figcaption&amp;gt;&#xA;                {{- end }}&#xA;                &amp;lt;/figure&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;            {{ if eq (mod $i 3) 2 }}&#xA;                &amp;lt;/div&amp;gt;&#xA;            {{ end }}&#xA;            {{ $i = add $i 1 }}&#xA;        {{ end }}&#xA;    {{ end }}&#xA;    {{ end }}&#xA;{{ end }}&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Lego 2023</title>
      <link>https://miek.nl/galleries/2023-lego/</link>
      <pubDate>Sat, 18 Nov 2023 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2023-lego/</guid>
      <description>&lt;p&gt;Lego Stad Brickmegen.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ASCII art in motd</title>
      <link>https://miek.nl/2023/november/15/ascii-art-in-motd/</link>
      <pubDate>Wed, 15 Nov 2023 06:17:36 +0000</pubDate>
      <guid>https://miek.nl/2023/november/15/ascii-art-in-motd/</guid>
      <description>&lt;p&gt;I wanted a nicer login experience (see image above) when logging into my server.&lt;/p&gt;&#xA;&lt;p&gt;For this I used the following sites, tools and steps.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.svgrepo.com/&#34;&gt;https://www.svgrepo.com/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://asciiart.club/&#34;&gt;https://asciiart.club/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Little Go program from below&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Steps:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Search a nice SVG image at &amp;ldquo;svgrepo&amp;rdquo; and save it;&lt;/li&gt;&#xA;&lt;li&gt;Upload it to &amp;ldquo;asciiart&amp;rdquo;, and generate an ASCII art you are happy with;&lt;/li&gt;&#xA;&lt;li&gt;Download the BBCode variant of the image and (if you want colors) run the program to&#xA;translate &lt;code&gt;[color=#...]&lt;/code&gt; to terminal control characters.&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;go run replace.go &amp;lt;image&amp;gt; &amp;amp;&amp;amp; cat out&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The used program is hacky, but does the job. Also used &amp;ldquo;inkscape&amp;rdquo; to fiddle with another logo, and&#xA;made that output something decent as well.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Nice Morning View</title>
      <link>https://miek.nl/2023/november/13/nice-morning-view/</link>
      <pubDate>Mon, 13 Nov 2023 19:05:54 +0100</pubDate>
      <guid>https://miek.nl/2023/november/13/nice-morning-view/</guid>
      <description>&lt;p&gt;A foggy morning view.&lt;/p&gt;</description>
    </item>
    <item>
      <title>DNSSEC Too Complex</title>
      <link>https://miek.nl/2023/november/04/dnssec-too-complex/</link>
      <pubDate>Sat, 04 Nov 2023 15:18:59 +0100</pubDate>
      <guid>https://miek.nl/2023/november/04/dnssec-too-complex/</guid>
      <description>&lt;figure class=&#34;left&#34; &gt;&#xA;    &lt;img src=&#34;https://miek.nl/images/2023/bike-meme-dnssec.jpg&#34;  loading=&#34;lazy&#34;  /&gt;&#xA;    &#xA;      &lt;figcaption class=&#34;center&#34; &gt;Deploying DNSSEC.&lt;/figcaption&gt;&#xA;    &#xA;  &lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;Even though I co-authored &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc4641&#34;&gt;RFC 4641&lt;/a&gt;, laying out how&#xA;you should run DNSSEC - I think in retrospect that BCP is way too complex, ah the sin of youth.&lt;/p&gt;&#xA;&lt;p&gt;You should (if you want to run DNSSEC) run with a single key (called common-signing-key; CSK) and&#xA;never roll your keys. This is what &lt;a href=&#34;https://coredns.io&#34;&gt;CoreDNS&amp;rsquo;&lt;/a&gt;&#xA;&lt;a href=&#34;https://coredns.io/plugins/sign/&#34;&gt;sign&lt;/a&gt; plugin implements and what I use.&lt;/p&gt;&#xA;&lt;p&gt;Also see &lt;a href=&#34;https://mastodon.cloud/@miek/111352709824615368&#34;&gt;this Mastodon post&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Groesbeek&#39;s Gruwelijkste 2023</title>
      <link>https://miek.nl/galleries/2023-groesbeeks-gruwelijkste/</link>
      <pubDate>Sun, 17 Sep 2023 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2023-groesbeeks-gruwelijkste/</guid>
      <description>&lt;p&gt;Op 17 September Groesbeek&amp;rsquo;s Gruwelijkste gereden. De 75 km.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Nvim Debian Pkg</title>
      <link>https://miek.nl/2023/september/10/nvim-debian-pkg/</link>
      <pubDate>Sun, 10 Sep 2023 11:20:31 +0200</pubDate>
      <guid>https://miek.nl/2023/september/10/nvim-debian-pkg/</guid>
      <description>&lt;p&gt;NVIM stopped making Debian packages a while back, so here is a short note on how to&#xA;do this yourself. Had a hard time finding this info, hence reproduced here. Assuming you&amp;rsquo;ve&#xA;got the source.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;make CMAKE_BUILD_TYPE=Release&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cd build &amp;amp;&amp;amp; cpack -G DEB&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sudo dpkg -i nvim-linux64.deb&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&amp;hellip; and of course you then find the &lt;a href=&#34;https://github.com/neovim/neovim/wiki/Building-Neovim#quick-start&#34;&gt;authoritative&#xA;text&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you use &lt;code&gt;RelWithDebInfo&lt;/code&gt; an ever growing log file will be created in &lt;code&gt;~/.local/state/nvim/log&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Zomer 2023</title>
      <link>https://miek.nl/galleries/2023-zomer/</link>
      <pubDate>Thu, 10 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/galleries/2023-zomer/</guid>
      <description>&lt;p&gt;Onze zomer naar Engeland en Oost-Duitsland.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Freedom Internet IPv6 with Ubiquity Edge Router</title>
      <link>https://miek.nl/2023/january/13/freedom-internet-ipv6-with-ubiquity-edge-router/</link>
      <pubDate>Fri, 13 Jan 2023 15:25:09 +0100</pubDate>
      <guid>https://miek.nl/2023/january/13/freedom-internet-ipv6-with-ubiquity-edge-router/</guid>
      <description>&lt;p&gt;Had a pretty hard time getting IPv6 going with &lt;a href=&#34;https://freedom.nl&#34;&gt;Freedom Internet&lt;/a&gt; (a Dutch ISP),&#xA;so this is mostly a &amp;ldquo;note to myself&amp;rdquo;. Turns out I wasn&amp;rsquo;t going crazy and for (some?) reason the&#xA;wizard doesn&amp;rsquo;t set the default route for IPv6.&lt;/p&gt;&#xA;&lt;p&gt;Basically what I did is: follow the Basic Setup wizard and enable IPv6 where you see it. This doesn&amp;rsquo;t&#xA;not make IPv6 work in this case. So I needed to do the following from the command line when ssh-ed into&#xA;the router (after configure):&lt;/p&gt;</description>
    </item>
    <item>
      <title>Provisioning Services</title>
      <link>https://miek.nl/2022/november/15/provisioning-services/</link>
      <pubDate>Tue, 15 Nov 2022 07:35:00 +0000</pubDate>
      <guid>https://miek.nl/2022/november/15/provisioning-services/</guid>
      <description>&lt;p&gt;There is a large gap between folks running their own machines and provisioning those and folks&#xA;running Kubernetes and having Gitops at their disposal. In the latter case you can just put some&#xA;YAML in Git and apply it in Kubernetes. Folks running their own machines on the other hand&amp;hellip; are&#xA;not so lucky.&lt;/p&gt;&#xA;&lt;p&gt;Several &amp;ldquo;solutions&amp;rdquo; have existed for years, the umbrella term being &amp;ldquo;provisioning systems&amp;rdquo;, cfengine&#xA;(one of the first), puppet, ansible and more. These work, but are (too?) powerful in that they allow&#xA;actions and edits on the system being provisioned. This creates (hidden) problems when you&amp;rsquo;re asking&#xA;yourself questions like: &amp;ldquo;Is the system&amp;rsquo;s state correct and in sync?&amp;rdquo;; &amp;ldquo;Can we easily rollback to a&#xA;previously working version?&amp;rdquo;; &amp;ldquo;What content should file /path/to/file actually have?&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tweets of November 12 2022</title>
      <link>https://miek.nl/2022/november/12/tweets-of-november-12-2022/</link>
      <pubDate>Sat, 12 Nov 2022 00:00:00 +0000</pubDate>
      <guid>https://miek.nl/2022/november/12/tweets-of-november-12-2022/</guid>
      <description>&lt;p&gt;Replying to &lt;a href=&#34;https://twitter.com/lucasdicioccio/status/1591176840366141440&#34;&gt;@lucasdicioccio&lt;/a&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I happened to have an account laying around https://mastodon.cloud/@miek&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/miekg/status/1591332043493109762&#34;&gt;Sat Nov 12 07:28:19 +0000 2022&lt;/a&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
