<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Tom Meurs</title>
    <link>https://tommeurs.nl/en/</link>
    <description>Recent content on Tom Meurs</description>
    <generator>Hugo</generator>
    <language>en</language>
    <copyright>© Tom Meurs</copyright>
    <lastBuildDate>Tue, 06 Oct 2026 09:00:00 +0200</lastBuildDate>
    <atom:link href="https://tommeurs.nl/en/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Talos Linux Vendor Lock-In: Five Questions, Run on My Own Nodes</title>
      <link>https://tommeurs.nl/en/posts/talos-linux-vendor-lock-in/</link>
      <pubDate>Tue, 06 Oct 2026 09:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/talos-linux-vendor-lock-in/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I ran the five questions from my licence post on the OS under my own cluster. The licence holds. The &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;A Linux distribution with no shell, no SSH and no package manager, managed entirely through an API. The node is configuration rather than a machine you log into.&#34;&gt;Talos&lt;/span&gt;&#xA; Linux vendor lock-in sits in two defaults that point at Sidero&amp;rsquo;s servers, the &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Business Source License 1.1: the source is published and free to use, except for the use the licensor names, usually a hosted service that competes with its own. Each release converts to an open source licence after a fixed number of years.&#34;&gt;BSL&lt;/span&gt;&#xA; code Sidero keeps adding around the &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Mozilla Public License 2.0: a file-level copyleft licence. Changes to MPL files must stay open when you distribute them, while code in other files may carry any licence.&#34;&gt;MPL&lt;/span&gt;&#xA; core, and a company Yardi has owned since 14 September.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Supply Chain Security in GitLab CI: SBOM, cosign, and the Policy That Blocks</title>
      <link>https://tommeurs.nl/en/posts/supply-chain-security-gitlab-ci/</link>
      <pubDate>Tue, 29 Sep 2026 09:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/supply-chain-security-gitlab-ci/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; A pipeline that scans images and writes an SBOM, with nothing checking either at admission, had been green for a year and had stopped nothing. Four steps below: an SBOM Trivy can read back, a cosign signature on the digest with the key in Vault, the SBOM attached as an attestation, and a Kyverno policy that refuses the rest. Then a table of which SLSA Build L3 requirements a self-hosted GitLab runner meets, and the two it doesn&amp;rsquo;t.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Your Dependency&#39;s Business Model Is Part of Your Threat Model</title>
      <link>https://tommeurs.nl/en/posts/license-change-supply-chain-risk/</link>
      <pubDate>Wed, 23 Sep 2026 19:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/license-change-supply-chain-risk/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; A vendor freezing its free edition belongs in your risk register next to the expiring certificate. Thirty-six dated cases below, three kinds of event, and five questions to score your own stack. My own register had the Vault row missing for three years.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;On 11 September, Portainer&amp;rsquo;s CEO published &lt;a href=&#34;https://www.portainer.io/blog/portainer-3-0-is-coming&#34;&gt;&amp;ldquo;Portainer 3.0 is coming, and here&amp;rsquo;s what it means for you&amp;rdquo;&lt;/a&gt;. I read it the Monday after and shrugged.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s what it says. 3.0 is a Kubernetes-first codebase for enterprise customers, and &amp;ldquo;we are not cutting a separate CE build of it&amp;rdquo;. Community Edition stays on 2.x. 2.45 LTS &amp;ldquo;is the last release in the 2.x line&amp;rdquo;. A few days later they added a clarification: 2.45 keeps getting security fixes, bug fixes and back-ports of any 3.x feature that has a Docker API equivalent, &amp;ldquo;for as long as that LTS is supported&amp;rdquo;. The &lt;a href=&#34;https://docs.portainer.io/start/lifecycle&#34;&gt;lifecycle page&lt;/a&gt; puts that at May 2027. Want 3.x for free? There&amp;rsquo;s a Business Edition key called &lt;a href=&#34;https://www.portainer.io/take-3&#34;&gt;3 Nodes Free&lt;/a&gt;, one per organisation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NIS2 for Platform Teams: Which Control Satisfies Which Article</title>
      <link>https://tommeurs.nl/en/posts/nis2-for-platform-teams/</link>
      <pubDate>Sun, 20 Sep 2026 21:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/nis2-for-platform-teams/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; The Cyberbeveiligingswet has applied since 15 August 2026. Below, the ten measures of &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Cbw art. 21: the duty of care. Appropriate and proportionate measures, of which paragraph 3 names ten.&#34;&gt;article 21&lt;/span&gt;&#xA; mapped onto controls that actually run, a Kyverno policy that proves one of them, the reporting deadlines as three Prometheus alerting rules, and the four duties no YAML covers. The first run of that policy found seven pods in my own cluster I&amp;rsquo;d have sworn were mirrored.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux Is for Everyone: Why This Blog Now Welcomes Beginners Too</title>
      <link>https://tommeurs.nl/en/posts/linux-is-for-everyone/</link>
      <pubDate>Thu, 11 Jun 2026 20:28:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/linux-is-for-everyone/</guid>
      <description>&lt;p&gt;My neighbour is 70 years old. He&amp;rsquo;s used Windows his whole life. Last month he asked me: &amp;ldquo;Tom, I keep hearing about Linux. Is that something for me too?&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;He&amp;rsquo;s not the first. Over the past year I&amp;rsquo;ve had the same question from friends, family and colleagues, each in their own shape. &amp;ldquo;I want to get off Windows, but where do I start?&amp;rdquo; &amp;ldquo;Is Linux hard?&amp;rdquo; &amp;ldquo;Can I still use my normal programs?&amp;rdquo; To me these are easy questions. I&amp;rsquo;ve been running Linux since SuSE 6.0, back when you picked your hardware by whether a Linux driver existed for it. If you&amp;rsquo;ve never seen a terminal, they&amp;rsquo;re not easy at all.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Data Poisoning: Reclaiming Your Privacy Through Offence</title>
      <link>https://tommeurs.nl/en/posts/data-poisoning-privacy/</link>
      <pubDate>Sun, 07 Jun 2026 21:43:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/data-poisoning-privacy/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s how privacy works today. You read the policy. You dismiss the cookie banner. You hunt through three settings menus for the opt-out toggle that someone buried on purpose. All of that to exercise a right that should&amp;rsquo;ve been the default. And while you&amp;rsquo;re still on the first paragraph of the terms of service, every click, scroll, hover and the exact timing of your keystrokes has already been harvested, packaged and sold. Somewhere along the way I stopped finding that strange, and that bothers me more than the harvesting does.&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVM/QEMU Scripts and Aliases: Making Virtualization Actually Usable</title>
      <link>https://tommeurs.nl/en/posts/kvm-qemu-scripts-aliases/</link>
      <pubDate>Wed, 03 Jun 2026 21:17:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kvm-qemu-scripts-aliases/</guid>
      <description>&lt;p&gt;I run VMs all day. A Kubernetes deployment I want to test, a distro I read about, Windows for that one stubborn application, an experiment I&amp;rsquo;d rather not run on my actual machine. KVM/QEMU is the right tool for all of it. It lives in the Linux kernel and runs close to native speed. Nothing in it phones home, and no vendor gets a say in what I do with my own hardware.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Infrastructure as Code for People Who Need to Understand</title>
      <link>https://tommeurs.nl/en/posts/infrastructure-as-code-control/</link>
      <pubDate>Sat, 30 May 2026 19:45:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/infrastructure-as-code-control/</guid>
      <description>&lt;p&gt;Someone opens a cloud console, clicks through a wizard, accepts a few defaults, and a resource appears. The dashboard goes green and everyone moves on. That&amp;rsquo;s still how a lot of infrastructure gets built in 2026, and I&amp;rsquo;ve built some of it that way myself.&lt;/p&gt;&#xA;&lt;p&gt;I can&amp;rsquo;t work like that for long. When I click a button and infrastructure appears, it feels borrowed. I want the configuration written down somewhere I can read it back, and I want to know why something exists, not only that it exists. The console gives me a green tick. It doesn&amp;rsquo;t give me any of that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Backup Strategy for Your Homelab: The 3-2-1 Rule in Practice</title>
      <link>https://tommeurs.nl/en/posts/homelab-backup-strategy/</link>
      <pubDate>Mon, 18 May 2026 19:30:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/homelab-backup-strategy/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Three copies, two kinds of media, one of them offsite. Restic for files, Velero for the cluster, a Backblaze bucket for the offsite copy, and a restore test on a schedule. Mine costs about €5 a month, and the restore test is the part I still have to make myself do.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Picture the disk in your &lt;a href=&#34;https://tommeurs.nl/en/posts/k3s-cluster-setup/&#34;&gt;homelab&lt;/a&gt; dying tonight. Not corrupting, not throwing SMART warnings for a week first, just gone. The git server with every repo you care about, the password vault, fifteen years of family photos, the home automation that runs the house. All of it on a drive that&amp;rsquo;s decided it&amp;rsquo;s done.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Terminal Multiplexing: tmux vs Zellij vs Screen</title>
      <link>https://tommeurs.nl/en/posts/terminal-multiplexing/</link>
      <pubDate>Thu, 14 May 2026 19:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/terminal-multiplexing/</guid>
      <description>&lt;p&gt;The first time it bit me I was halfway through a database migration over SSH. The train went into a tunnel, the WiFi dropped, and the process on the other end died with the connection. I sat looking at a dead prompt, wondering how much of the migration had committed.&lt;/p&gt;&#xA;&lt;p&gt;A multiplexer would have saved me that hour. The process keeps running on the server whether I&amp;rsquo;m attached or not, so a dropped connection costs me a reconnect and nothing else. I reattach and the work is where I left it. That one property is why a multiplexer goes on every machine I touch, before the editor and before the dotfiles.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tailscale for Homelab: Secure Remote Access Without Port Forwarding</title>
      <link>https://tommeurs.nl/en/posts/tailscale-homelab/</link>
      <pubDate>Sun, 10 May 2026 18:45:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/tailscale-homelab/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Tailscale puts every device I own on one WireGuard mesh, so I reach the cluster in the closet from a coffee shop without a single port forwarded on the router. Subnet router, exit node, the Kubernetes operator, ACLs, and Headscale for the part I&amp;rsquo;d rather host myself, in that order.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;My &lt;a href=&#34;https://tommeurs.nl/en/posts/k3s-cluster-setup/&#34;&gt;homelab cluster&lt;/a&gt; runs in a closet at home. I don&amp;rsquo;t. I work from coffee shops, from a client&amp;rsquo;s office, and now and then from a hotel with WiFi that seems to resent me. I still want my own machines while I&amp;rsquo;m out there.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building an Internal Developer Platform: Where to Start</title>
      <link>https://tommeurs.nl/en/posts/internal-developer-platform/</link>
      <pubDate>Wed, 06 May 2026 19:30:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/internal-developer-platform/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; An Internal Developer Platform is a thin layer between what a developer wants and what the cluster demands. Mine is a Helm base chart, ArgoCD and a handful of Kyverno policies, about 500 lines of my own code. Start with those three, and add observability and a portal only when the tickets tell you to.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Should you build an Internal Developer Platform? Usually, yes. It&amp;rsquo;s the how that wrecks teams.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Grafana Dashboards That Actually Get Used</title>
      <link>https://tommeurs.nl/en/posts/grafana-dashboards-that-work/</link>
      <pubDate>Sat, 02 May 2026 20:15:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/grafana-dashboards-that-work/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Each dashboard answers one question, and within five seconds I know whether I need to care. Four kinds of dashboard cover everything, variables and links tie them together, and the JSON lives in Git. My homelab runs five, and anything that goes a month unopened gets deleted.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;You have Grafana. You have &lt;a href=&#34;https://tommeurs.nl/en/posts/prometheus-thanos-metrics/&#34;&gt;Prometheus metrics&lt;/a&gt;. You have &lt;a href=&#34;https://tommeurs.nl/en/posts/loki-kubernetes-logging/&#34;&gt;logs in Loki&lt;/a&gt; and &lt;a href=&#34;https://tommeurs.nl/en/posts/tempo-distributed-tracing/&#34;&gt;traces in Tempo&lt;/a&gt;. The data&amp;rsquo;s all there.&lt;/p&gt;&#xA;&lt;p&gt;You also have 47 dashboards nobody opens.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Chaos Engineering: Breaking Your Cluster to Make It Stronger</title>
      <link>https://tommeurs.nl/en/posts/chaos-engineering-kubernetes/</link>
      <pubDate>Tue, 28 Apr 2026 19:45:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/chaos-engineering-kubernetes/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Chaos engineering is breaking your own cluster on purpose, with the hypothesis written down first and a rollback ready. I run it on the homelab with Litmus: a weekly pod-delete, a monthly node drain, a game day every quarter. So far it has found four things the dashboard would never have shown me.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;My dashboard is a wall of green. Pods running, replicas matched, CPU comfortable, no alerts firing. I look at it and get that small hit of &amp;ldquo;everything&amp;rsquo;s fine.&amp;rdquo; And mostly it is. The cluster&amp;rsquo;s been up for weeks and nothing has fallen over.&lt;/p&gt;</description>
    </item>
    <item>
      <title>K3s Cluster Setup on Refurbished Mini-PCs</title>
      <link>https://tommeurs.nl/en/posts/k3s-cluster-setup/</link>
      <pubDate>Fri, 24 Apr 2026 21:12:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/k3s-cluster-setup/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Three refurbished mini-PCs, K3s with embedded etcd, kube-vip for one API address that survives a dead node, then MetalLB, Traefik and Longhorn on top. About €450 in hardware and an afternoon. Below are the commands, in the order I ran them.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Three mini-PCs sit on a shelf in my house. Between them they run my GitLab, my monitoring stack, home automation, file sync, a password manager, and a pile of other things I&amp;rsquo;d rather not hand to someone else&amp;rsquo;s computer. The whole setup cost less than one month of the managed Kubernetes bill for the same thing, and I know what every layer does because I put it there.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Longhorn vs Rook-Ceph: Kubernetes Storage Compared</title>
      <link>https://tommeurs.nl/en/posts/longhorn-vs-rook-ceph/</link>
      <pubDate>Mon, 20 Apr 2026 19:38:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/longhorn-vs-rook-ceph/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Longhorn and Rook-Ceph both give you replicated block storage that survives a node dying. Longhorn is one Helm install and a UI that shows you what a volume is doing. Rook-Ceph is Ceph with a Kubernetes operator around it, so you get block, object and filesystem storage, and the operations that come with them. I run Longhorn on three nodes. Below is why, and when I&amp;rsquo;d switch.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Run your first stateful workload on a self-hosted cluster and you find out fast that nobody hands out PersistentVolumes for free. There&amp;rsquo;s no cloud provider storage class to lean on. You&amp;rsquo;ve got your nodes, their disks, and a Postgres pod that won&amp;rsquo;t schedule. An hour of reading later you&amp;rsquo;re left with two names that keep coming up. &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Block storage for Kubernetes that replicates a volume across nodes. Simple to run and slower than Ceph, which is the trade it makes on purpose.&#34;&gt;Longhorn&lt;/span&gt;&#xA; and Rook-&lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;A distributed storage system that serves block, file and object from one cluster. Powerful, and heavy enough that running it is a job rather than a setting.&#34;&gt;Ceph&lt;/span&gt;&#xA;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quantum-safe GPG identity with multiple aliases</title>
      <link>https://tommeurs.nl/en/posts/quantum-safe-gpg-identity/</link>
      <pubDate>Sat, 18 Apr 2026 10:47:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/quantum-safe-gpg-identity/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; One GPG masterkey that only certifies, kept offline. Three aliases bound to it, so anyone can check they&amp;rsquo;re the same person. Ed25519 subkeys for signing and SSH, an ML-KEM plus X448 subkey for encryption so recorded ciphertext stays closed after a quantum computer shows up, and three backups that each assume the other two are gone. Needs GnuPG 2.5.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;A cryptographic signature still means exactly what it says. If the key is yours and the signature verifies, the content came from you. No vendor handed you that identity, no CA can pull it, no platform can suspend it. It exists because you generated the key, and it&amp;rsquo;s yours for as long as you hold the private half. Most of what gets called &amp;ldquo;online identity&amp;rdquo; is borrowed. A handle someone can ban, an email address the domain owner can take back the day they feel like it. A GPG signature sits outside all of that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Alerting That Works: From Alert Fatigue to Actionable Notifications</title>
      <link>https://tommeurs.nl/en/posts/alerting-that-works/</link>
      <pubDate>Thu, 16 Apr 2026 20:15:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/alerting-that-works/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Most default alert rules page on a number with no user behind it, and after a week of that you stop reading pages. I alert on error rate, P99 latency, a disk that fills within 24 hours and a certificate under seven days, about ten rules in total, each with a runbook. Alertmanager sends critical to the pager, warning to Slack during office hours, info nowhere. Everything that doesn&amp;rsquo;t need a human gets deleted.&lt;/p&gt;</description>
    </item>
    <item>
      <title>cert-manager: Automatic TLS Certificates in Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/cert-manager-kubernetes-tls/</link>
      <pubDate>Sun, 12 Apr 2026 21:38:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/cert-manager-kubernetes-tls/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; cert-manager watches Certificate resources, fetches the certificate from Let&amp;rsquo;s Encrypt, your own CA or Vault, stores it in a Secret and renews it 30 days before it expires. I run one DNS-01 ClusterIssuer through Cloudflare and one wildcard certificate, copy that Secret into the namespaces that need it, and let two Prometheus alerts tell me when a renewal is stuck. Nothing left to remember.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;For years my certificates renewed the way most people&amp;rsquo;s do. A calendar reminder, a manual &lt;code&gt;certbot&lt;/code&gt; run, and the hope that I&amp;rsquo;d get to it before the thing expired. It worked, right up to the morning a service started throwing cert errors at me and I had no idea why. The renewal cron had been failing for weeks. Quietly.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cilium: eBPF Networking for Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/cilium-ebpf-networking/</link>
      <pubDate>Wed, 08 Apr 2026 20:23:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/cilium-ebpf-networking/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Cilium is the CNI I run in every cluster. It replaces kube-proxy and its iptables chains with eBPF programs in the kernel, enforces network policies on identity and on HTTP paths, and Hubble shows me every flow and every drop. WireGuard between the pods, BGP to the switch, no sidecars. My production values are at the bottom.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The first time a service stopped resolving in one of my clusters, I spent an evening reading iptables chains. Hundreds of rules, generated by kube-proxy, evaluated top to bottom. I never found the problem. I restarted the node and it went away.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Distributed Tracing with Tempo and OpenTelemetry</title>
      <link>https://tommeurs.nl/en/posts/tempo-distributed-tracing/</link>
      <pubDate>Sat, 04 Apr 2026 19:47:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/tempo-distributed-tracing/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Tempo is where my traces go. The OpenTelemetry Collector receives spans from every service, tail sampling keeps every error and every slow request, and Tempo writes the rest to MinIO with three days of retention. From a span in Grafana I click through to the Loki lines with the same trace ID. My production values are at the bottom.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Your &lt;a href=&#34;https://tommeurs.nl/en/posts/prometheus-thanos-metrics/&#34;&gt;metrics&lt;/a&gt; say something is slow. Your &lt;a href=&#34;https://tommeurs.nl/en/posts/loki-kubernetes-logging/&#34;&gt;logs&lt;/a&gt; say errors happened. Fine. Which request failed, where did the latency come from, and which service in the chain ate the timeout? Neither of them can tell you.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Loki for Kubernetes Logging: The Prometheus-Like Approach</title>
      <link>https://tommeurs.nl/en/posts/loki-kubernetes-logging/</link>
      <pubDate>Tue, 31 Mar 2026 21:15:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/loki-kubernetes-logging/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Loki indexes labels and stores the log text as compressed chunks, so a month of logs fits on commodity hardware. The trade is full-text search. Below is the single-binary install I&amp;rsquo;d hand anyone first, the same chart on MinIO with three replicas, and the knobs I didn&amp;rsquo;t touch until the volume was real.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;You&amp;rsquo;ve got &lt;a href=&#34;https://tommeurs.nl/en/posts/prometheus-thanos-metrics/&#34;&gt;Prometheus for metrics&lt;/a&gt;, so you can already see what&amp;rsquo;s happening across your clusters. Metrics tell you request latency spiked at 14:32. They don&amp;rsquo;t tell you the payment service threw a null pointer because someone shipped a config change with a typo. For that you need the log line.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Thanos Remote Write: Push-Based Metrics for Edge and Multi-Cluster</title>
      <link>https://tommeurs.nl/en/posts/thanos-remote-write-push-architecture/</link>
      <pubDate>Fri, 27 Mar 2026 20:38:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/thanos-remote-write-push-architecture/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Thanos Receive turns the metrics flow around. Each edge Prometheus pushes samples over &lt;code&gt;remote_write&lt;/code&gt; to one central endpoint, buffers in its WAL when the link drops, and never sees an object storage credential. Below is the Receive StatefulSet, the hashring, the edge config, two ways to lock the endpoint down, and the hybrid I run with sidecars on the core clusters.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;In my &lt;a href=&#34;https://tommeurs.nl/en/posts/prometheus-thanos-metrics/&#34;&gt;previous post on Prometheus and Thanos&lt;/a&gt;, I set up the sidecar architecture. &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Gives Prometheus long-term storage in object storage and one query view across several Prometheus servers, without changing how Prometheus scrapes.&#34;&gt;Thanos&lt;/span&gt;&#xA; Sidecar runs next to Prometheus, uploads TSDB blocks to object storage, and exposes the data to the Querier over gRPC. For clusters in the same datacenter with a fat, stable link to the central infrastructure, I&amp;rsquo;ve got no complaints. Everything pulls, and everything can reach everything else.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Declarative Infrastructure as Compliance Documentation: Talos, NixOS, and Audit-Ready Systems</title>
      <link>https://tommeurs.nl/en/posts/declarative-infrastructure-compliance-certification/</link>
      <pubDate>Mon, 23 Mar 2026 19:28:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/declarative-infrastructure-compliance-certification/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Talos and NixOS boot from a file that says what the machine is. That file is what an ISO 27001, SOC 2 or NIS2 auditor asks for, so the evidence collection shrinks to a git log, a diff with no output and an inventory dump. Below is the mapping from config to control, the scripts, and the part that stays hard work.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;An ISO 27001 audit starts weeks before the auditor shows up, with someone collecting screenshots. Configuration panels, firewall rules, a dashboard that shows which patches went out. Then the Word documents that describe what the systems are supposed to do. Then the change tickets, dug out of the ticketing system, each one pointing at a &amp;ldquo;server maintenance&amp;rdquo; nobody can reconstruct six months later. Everyone treats this as the price of being in business. I did too, for years.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NixOS as a Hypervisor: KVM and QEMU Can Do Everything</title>
      <link>https://tommeurs.nl/en/posts/nixos-hypervisor-kvm-qemu/</link>
      <pubDate>Thu, 19 Mar 2026 21:52:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/nixos-hypervisor-kvm-qemu/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; KVM and QEMU are the engine inside Proxmox and most of the cloud you rent. On NixOS, with libvirt on top, that engine is one block of config, and live migration, memory ballooning, GPU passthrough, SR-IOV and CPU pinning are each a command or an XML snippet away. What Proxmox adds is the dashboard and the delegation, and I&amp;rsquo;m honest below about how much that&amp;rsquo;s worth.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Ask around how to run a &amp;ldquo;real&amp;rdquo; hypervisor at home and you get the same shortlist. VMware, Hyper-V, or at minimum Proxmox. Something with a web UI, a clustering tab and a marketing page full of enterprise features. The shortlist is so well worn that running VMs without one of those products feels like cutting corners. I don&amp;rsquo;t blame anyone for that. The marketing is good.&lt;/p&gt;</description>
    </item>
    <item>
      <title>NixOS vs Talos for Kubernetes Nodes: Two Flavors of Immutable Infrastructure</title>
      <link>https://tommeurs.nl/en/posts/nixos-vs-talos-kubernetes-nodes/</link>
      <pubDate>Sun, 15 Mar 2026 20:37:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/nixos-vs-talos-kubernetes-nodes/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Talos and NixOS are both declarative and both can be immutable, and that&amp;rsquo;s about where the resemblance stops. Talos runs Kubernetes and nothing else, with no shell to drift in. NixOS is a full Linux where the whole machine is one Nix config. I run Talos on my cluster nodes and NixOS on the machines around them, and this post is how I got to that split.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve written about &lt;a href=&#34;https://tommeurs.nl/en/posts/talos-linux-immutable-kubernetes/&#34;&gt;Talos Linux&lt;/a&gt; as the immutable Kubernetes OS, and I&amp;rsquo;ve compared &lt;a href=&#34;https://tommeurs.nl/en/posts/arch-vs-nixos-workstation/&#34;&gt;Arch vs NixOS for workstations&lt;/a&gt;. After both, the same question kept arriving in my inbox. Why not NixOS on the Kubernetes nodes too?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Talos Linux: The Immutable Kubernetes OS That Changed How I Think About Nodes</title>
      <link>https://tommeurs.nl/en/posts/talos-linux-immutable-kubernetes/</link>
      <pubDate>Wed, 11 Mar 2026 21:15:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/talos-linux-immutable-kubernetes/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Talos Linux is a Linux that runs Kubernetes and nothing else. No SSH, no shell, no package manager. Every change goes through an API and a YAML file in Git. I&amp;rsquo;ve run my nodes on it for three years, and this post is how I stopped missing the shell.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The first time I tried to SSH into a &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;A Linux distribution with no shell, no SSH and no package manager, managed entirely through an API. The node is configuration rather than a machine you log into.&#34;&gt;Talos&lt;/span&gt;&#xA; node, I got nothing. No shell, no connection, not even a login prompt. I sat there for a minute wondering how I was supposed to debug a machine I couldn&amp;rsquo;t get into.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Lost Art of Software Optimization: What Demoscene Taught Us About Sustainability</title>
      <link>https://tommeurs.nl/en/posts/demoscene-optimization-sustainability/</link>
      <pubDate>Sat, 07 Mar 2026 20:42:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/demoscene-optimization-sustainability/</guid>
      <description>&lt;p&gt;Most of us ship software the same way now. Pick a framework, pull in a few hundred dependencies, and the service idles at a gigabyte of RAM before it does its first useful piece of work. Nobody profiles it. If it&amp;rsquo;s slow, you scale up. Compute is cheap, your time isn&amp;rsquo;t, and the bill goes to someone else. I don&amp;rsquo;t say that as a complaint. I&amp;rsquo;ve done it, and I&amp;rsquo;ll do it again on the next deadline.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Arch vs NixOS as a Workstation: Professional and Personal Use</title>
      <link>https://tommeurs.nl/en/posts/arch-vs-nixos-workstation/</link>
      <pubDate>Tue, 03 Mar 2026 21:28:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/arch-vs-nixos-workstation/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I&amp;rsquo;ve run Arch and NixOS as my daily machine, and today it&amp;rsquo;s Arch on both desktops and NixOS on the servers. Arch&amp;rsquo;s reputation for breaking is mostly a missing snapshot. With btrfs, Snapper, dotfiles in git and a package list, a rollback takes 2 minutes and the fear of updates goes away. NixOS earns its learning curve when several machines have to stay identical, and on a server I wouldn&amp;rsquo;t run anything else.&lt;/p&gt;</description>
    </item>
    <item>
      <title>CTF and Forensics Skills That Make You a Better DevOps Engineer</title>
      <link>https://tommeurs.nl/en/posts/ctf-skills-for-devops/</link>
      <pubDate>Fri, 27 Feb 2026 19:52:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/ctf-skills-for-devops/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I spend my evenings on Hack The Box and it&amp;rsquo;s made me better at my day job, which is platform engineering and has nothing to do with pentesting. The first ten minutes on a &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Capture The Flag: a security exercise where you break into a deliberately vulnerable system and prove it by retrieving a planted token, the flag.&#34;&gt;CTF&lt;/span&gt;&#xA; box and the first ten minutes on a broken production server are the same loop, with &amp;ldquo;flag&amp;rdquo; swapped for &amp;ldquo;incident&amp;rdquo;. Below is the toolkit that loop runs on, from one host up to a Kubernetes pod, with the CTF use and the work use side by side for every command.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simulation, Emulation, Virtualization, and Containers: The Restaurant Metaphor</title>
      <link>https://tommeurs.nl/en/posts/simulation-emulation-virtualization-containers/</link>
      <pubDate>Mon, 23 Feb 2026 20:18:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/simulation-emulation-virtualization-containers/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Simulation models a thing without running it. Emulation runs it by rebuilding the hardware in software. Virtualization runs several complete operating systems on one machine. Containers run several apps on one kernel. Below, one restaurant per term, a table, and the four mix-ups I hear most.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;So what&amp;rsquo;s the difference between a container and a virtual machine?&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;I get this question a lot, usually from someone smart who&amp;rsquo;s been nodding along in meetings and doesn&amp;rsquo;t quite want to admit they&amp;rsquo;re fuzzy on it. The honest answer is that most explanations make it worse. They open with &amp;ldquo;hypervisor&amp;rdquo;, &amp;ldquo;kernel sharing&amp;rdquo; and &amp;ldquo;hardware abstraction&amp;rdquo;, and now the person has four new terms to be confused about instead of one.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Zero Trust Explained: The Hotel Key Card Metaphor</title>
      <link>https://tommeurs.nl/en/posts/zero-trust-explained/</link>
      <pubDate>Thu, 19 Feb 2026 21:34:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/zero-trust-explained/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; The old model is a castle. Get past the wall and you&amp;rsquo;re trusted everywhere inside. Zero trust is a hotel. Your key card opens your room, the gym if you booked it, and nothing else, and every door checks the card every time. Below, the three principles, a day in that hotel, and what the key card turns into once the doors are software.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;So what is this zero trust thing everyone keeps talking about?&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Learn the Defaults: Why Portability Beats Customization</title>
      <link>https://tommeurs.nl/en/posts/learn-the-defaults/</link>
      <pubDate>Sun, 15 Feb 2026 19:47:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/learn-the-defaults/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I spent years polishing a vim and tmux setup, then sat useless in front of a stock vim on a production server. So I learned the defaults I&amp;rsquo;d been overriding all along, and moved my customizations on top of them instead of in place of them. What that looks like for vim, tmux and the shell tools, and the four checks I use to find the gaps.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;For years my setup was the thing I was proudest of. A dotfiles repo with commits going back further than some of my jobs, a vim config that pulled in thirty plugins, the tmux prefix moved somewhere comfortable, a prompt that took a weekend to get right. Down to the last keybinding, it was mine. On my laptop I was fast, and I hardly thought about the tools at all. Muscle memory did the work.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dotfile Management with mise and chezmoi: The Perfect Combo</title>
      <link>https://tommeurs.nl/en/posts/dotfile-management-mise-chezmoi/</link>
      <pubDate>Wed, 11 Feb 2026 20:23:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/dotfile-management-mise-chezmoi/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Six ways of syncing dotfiles later, the one I kept is chezmoi for the files and mise for the tool versions, with the mise config living inside the chezmoi repo. Templates handle the work laptop against the personal desktop, age handles the secrets, and a fresh machine is one command and about five minutes. The walk-through goes from one managed file to the bootstrap I run for real.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;My &lt;code&gt;.zshrc&lt;/code&gt; is older than some of my coworkers&amp;rsquo; careers. Same for my &lt;code&gt;.vimrc&lt;/code&gt; and my tmux config. They&amp;rsquo;ve grown into a setup that does exactly what I want, and I&amp;rsquo;d be lost without them. The catch is that I run more than one machine. A laptop, a desktop, now and then a throwaway VM for testing. For years, keeping those in sync was a pile of hacks I didn&amp;rsquo;t trust.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Data-Driven Kubernetes Migration: Why You Need Metrics Before You Move</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-resource-sizing/</link>
      <pubDate>Sun, 08 Feb 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-resource-sizing/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; An e-commerce client moved a PHP monolith to EKS in October, two weeks before Black Friday, with resource limits guessed from the old server specs. Mid-morning the pods hit their memory limit, died in a loop for four hours, and the estimate was €240,000 in lost revenue. The second half is how to get those numbers from load tests and VPA recommendations instead of guessing them.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;We want to migrate to Kubernetes by November.&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>K8sGPT with a Local 70B Model on Apple Silicon</title>
      <link>https://tommeurs.nl/en/posts/k8sgpt-local-llm-cluster-management/</link>
      <pubDate>Thu, 05 Feb 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/k8sgpt-local-llm-cluster-management/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I pointed K8sGPT at a Llama 3.3 70B model running on a Mac Studio in my own office, so no cluster metadata leaves the network, and fed it three broken workloads. It found all three and wrote fixes I&amp;rsquo;d accept from a colleague, except for the resource numbers, which it made up. Assisted diagnosis works, at 25 seconds a query. Autonomous cluster management is still marketing, and the security section is why I wouldn&amp;rsquo;t let a model change anything on its own.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Privacy Matters More Than Ever</title>
      <link>https://tommeurs.nl/en/posts/why-privacy-matters-now/</link>
      <pubDate>Mon, 02 Feb 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/why-privacy-matters-now/</guid>
      <description>&lt;p&gt;Your phone logged where you slept before you woke up. You check Gmail, search something on Google, message a friend on WhatsApp, pay for coffee with a card and walk past a dozen cameras before lunch. None of that feels like surveillance. It feels like a normal morning.&lt;/p&gt;&#xA;&lt;p&gt;It felt the same five years ago, and I want to show you what changed in between. The comfortable version of privacy, &amp;ldquo;I have nothing to hide&amp;rdquo;, has quietly stopped being true, and I think most people haven&amp;rsquo;t noticed. Three things happened at once. On its own each one is manageable. Together they&amp;rsquo;re what worries me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Hardware Ownership Paradox: When Sovereignty Gets Expensive</title>
      <link>https://tommeurs.nl/en/posts/hardware-ownership-paradox/</link>
      <pubDate>Fri, 30 Jan 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/hardware-ownership-paradox/</guid>
      <description>&lt;p&gt;In my &lt;a href=&#34;https://tommeurs.nl/en/posts/self-hosting-for-everyone/&#34;&gt;previous post about self-hosting for everyone&lt;/a&gt; I drew a hopeful picture of managed self-hosting, where anyone can own their data. I skipped over something, and it&amp;rsquo;s been bugging me since. Hardware costs money, and the sum comes out very differently depending on whether a business or a person is paying.&lt;/p&gt;&#xA;&lt;p&gt;So here are two rules. Both sound reasonable on their own. Then I&amp;rsquo;ll put them in the same room.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Self-Hosting for Everyone: A Vision for Digital Agency</title>
      <link>https://tommeurs.nl/en/posts/self-hosting-for-everyone/</link>
      <pubDate>Tue, 27 Jan 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/self-hosting-for-everyone/</guid>
      <description>&lt;p&gt;Most people keep their photos at Google, their mail at Gmail, their documents in whatever cloud came with the phone and their passwords in a browser built by an advertising company. Every byte sits on a server they don&amp;rsquo;t own, under terms they didn&amp;rsquo;t read, in a country they didn&amp;rsquo;t check. Nobody finds that strange anymore, because the alternative looks like a second job.&lt;/p&gt;&#xA;&lt;p&gt;I want to talk about that alternative, and about why it sits behind a wall most people will never climb.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The space container thought experiment: systems thinking for survival</title>
      <link>https://tommeurs.nl/en/posts/spaceship-thought-experiment/</link>
      <pubDate>Tue, 20 Jan 2026 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/spaceship-thought-experiment/</guid>
      <description>&lt;p&gt;You wake up. It&amp;rsquo;s dark. Somewhere a fan is humming.&lt;/p&gt;&#xA;&lt;p&gt;Your eyes adjust. You&amp;rsquo;re in a container. Metal walls, a few small windows, and behind them stars. Just stars. No Earth anywhere.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a note taped to the wall:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;You have everything you need to survive. Nothing goes in, nothing goes out. Good luck.&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I bring this one up with friends when the evening has gone quiet enough for it. It sounds like science fiction, and the first reaction is usually a joke about the toilet. Then somebody asks what&amp;rsquo;s in the room, and we&amp;rsquo;re off. What the experiment takes away is an assumption I&amp;rsquo;d never said out loud before I ran it. That there&amp;rsquo;s an &amp;ldquo;outside&amp;rdquo; that absorbs my mistakes and refills my supplies.&lt;/p&gt;</description>
    </item>
    <item>
      <title>When not to use Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/when-not-to-use-kubernetes/</link>
      <pubDate>Sat, 17 Jan 2026 10:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/when-not-to-use-kubernetes/</guid>
      <description>&lt;p&gt;I write a lot about Kubernetes, and I run it at home every day. I like it.&lt;/p&gt;&#xA;&lt;p&gt;So it might surprise you that I spend a fair amount of my time talking people out of it.&lt;/p&gt;&#xA;&lt;p&gt;The situation I keep walking into goes like this. A small team, one product, a roadmap full of features customers are waiting for, and someone has decided the first milestone is a Kubernetes cluster. Three nodes minimum, etcd, a &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Container Network Interface: the plugin contract Kubernetes uses to give a pod its network. Cilium, Calico and Flannel are implementations of it.&#34;&gt;CNI&lt;/span&gt;&#xA;, an ingress controller, cert-manager, a monitoring stack. Weeks of work before a single customer sees anything. Everyone nods along, because that&amp;rsquo;s what a serious setup is supposed to look like.&lt;/p&gt;</description>
    </item>
    <item>
      <title>YubiKey &#43; Pass &#43; GPG &#43; SSH: One Key to Rule Them All</title>
      <link>https://tommeurs.nl/en/posts/yubikey-pass-gpg-ssh/</link>
      <pubDate>Tue, 13 Jan 2026 17:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/yubikey-pass-gpg-ssh/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; One YubiKey carries a GPG key with a signing, an encryption and an authentication subkey. gpg-agent hands the authentication subkey to SSH, git signs with the signing subkey and pass decrypts with the encryption subkey, so one PIN in the morning and a touch per action replace every password I used to type. The SSH part alone is three steps and worth doing on its own.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Every morning I plug in my YubiKey, type one PIN, and that&amp;rsquo;s the last secret I type until I pull it out again. SSH to a server, no password. Sign a commit, no passphrase. Pull a secret out of pass, touch the key. One thing in a USB port, and the rest of the day my authentication happens without me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pass: the Unix password manager that just works</title>
      <link>https://tommeurs.nl/en/posts/pass-password-manager/</link>
      <pubDate>Sat, 10 Jan 2026 12:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/pass-password-manager/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; pass keeps each password as a GPG-encrypted file in a directory, and the directory is the whole data model. &lt;code&gt;pass -c email/gmail&lt;/code&gt; puts a password in your clipboard from any terminal, &lt;code&gt;pass git push&lt;/code&gt; backs the store up, and the fzf script further down is how I look up every password I have. The price is GPG key management, and it&amp;rsquo;s a real price.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I used KeePass for years. Then 1Password. Then Bitwarden. All decent tools, and every one of them was too much for what I asked of it. Too much UI, too many features, and a password always lived on the other side of an app I had to alt-tab into. A small interruption, and they added up.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GPG explained: from first key to daily use</title>
      <link>https://tommeurs.nl/en/posts/gpg-beginners-guide/</link>
      <pubDate>Tue, 06 Jan 2026 19:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/gpg-beginners-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; GPG encrypts files and signs things, and it sits under pass, under signed git commits and under the checksums maintainers publish. One command gives you a working keypair in five minutes. Subkeys and a YubiKey come later, if ever, and the UX is bad enough that I complain about it at length below.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;GPG is a tool I kept meaning to learn and didn&amp;rsquo;t, for years. The docs are a wall of text, the terminology is its own dialect, and the error messages are cryptic in both senses of the word.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Taskwarrior, Timewarrior and Vit: The Ultimate CLI Productivity Stack</title>
      <link>https://tommeurs.nl/en/posts/taskwarrior-timewarrior-vit-tutorial/</link>
      <pubDate>Sat, 03 Jan 2026 15:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/taskwarrior-timewarrior-vit-tutorial/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Taskwarrior, timewarrior and vit are my task list, my time tracking and the vim-style screen on top, all in the terminal and all plain text in &lt;code&gt;~/.task&lt;/code&gt;. Two commands get you started. The rest of this post is what I bolted on afterwards, from projects and dependencies to a self-hosted sync server, and you can stop at any section.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For context on how my brain works, see &lt;a href=&#34;https://tommeurs.nl/en/posts/working-with-audhd-brain/&#34;&gt;Working with an AuDHD Brain&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why I self-host everything: on sovereignty, agency and control</title>
      <link>https://tommeurs.nl/en/posts/sovereign-infrastructure/</link>
      <pubDate>Tue, 30 Dec 2025 18:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/sovereign-infrastructure/</guid>
      <description>&lt;p&gt;For a long time the cloud was just the water I swam in. I provisioned managed Kubernetes, clicked through the console, pasted a Terraform module someone else had written, and shipped. It worked. The bill landed every month, the dashboards stayed green, and I didn&amp;rsquo;t look underneath. Why would I? I trusted it the way you trust a lift. Press the button, doors open.&lt;/p&gt;&#xA;&lt;p&gt;Then one afternoon a managed service fell over and I sat there with nothing to debug. No host to SSH into, no log I was allowed to read, nothing underneath it I could open up. The status page said &amp;ldquo;investigating&amp;rdquo;. Refreshing a page someone else controlled was the whole of my afternoon.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Working with an AuDHD brain: why I automate everything</title>
      <link>https://tommeurs.nl/en/posts/working-with-audhd-brain/</link>
      <pubDate>Sat, 27 Dec 2025 14:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/working-with-audhd-brain/</guid>
      <description>&lt;p&gt;For a long time I thought the problem was me.&lt;/p&gt;&#xA;&lt;p&gt;I have &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Autism combined with ADHD. The author has the inattentive presentation of ADHD, and writes about what that means for infrastructure work rather than about the diagnosis.&#34;&gt;AuDHD&lt;/span&gt;&#xA;, autism and ADHD together. The ADHD is ADHD-PI, the inattentive kind, without the hyperactivity most people picture when they hear the word. For years I treated the whole thing as a defect I&amp;rsquo;d train away. I bought the planners. I read the productivity books. Every week I told myself that Monday I&amp;rsquo;d finally be disciplined.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Unbreakable - My Fascination.</title>
      <link>https://tommeurs.nl/en/posts/unbreakable/</link>
      <pubDate>Tue, 23 Dec 2025 20:00:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/unbreakable/</guid>
      <description>&lt;p&gt;As a kid I called the things that fascinated me &lt;strong&gt;unbreakable&lt;/strong&gt;. Indestructible never fit, because indestructible means it never breaks. Unbreakable means it keeps working &lt;em&gt;after&lt;/em&gt; it breaks.&lt;/p&gt;&#xA;&lt;p&gt;I know exactly when it started. A photo of an A-10 Thunderbolt II back from a mission with half a wing gone, the tail in tatters and the fuselage full of holes. It still brought its pilot home.&lt;/p&gt;&#xA;&lt;p&gt;Luck had nothing to do with it. Somebody sat at a drawing board years before that mission and decided the plane had to come home looking like that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Prometheus and Thanos: Metrics at Scale</title>
      <link>https://tommeurs.nl/en/posts/prometheus-thanos-metrics/</link>
      <pubDate>Sun, 31 Aug 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/prometheus-thanos-metrics/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Prometheus on its own keeps a couple of weeks of metrics on local disk and can&amp;rsquo;t answer a question across clusters. Thanos puts a sidecar next to each Prometheus, ships the blocks to object storage, and puts a querier in front that reads all of it back through the same PromQL. Below is the install, the four components, the HA and multi-cluster wiring, and the numbers I run in production.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes RBAC: Least Privilege in Practice</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-rbac-least-privilege/</link>
      <pubDate>Tue, 19 Aug 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-rbac-least-privilege/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Kubernetes ships with a permission model that hands every pod a token and lets the default service account collect rights nobody remembers granting. Least privilege means a service account per workload, no token unless the app talks to the API, and roles that name the namespace, the resource and the verb. Below are the four RBAC resources, the five settings that cap the blast radius, the bindings I copy most often, and how I check and enforce all of it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Runtime Security with Falco: Detect Suspicious Behavior in Your Cluster</title>
      <link>https://tommeurs.nl/en/posts/falco-runtime-security/</link>
      <pubDate>Thu, 07 Aug 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/falco-runtime-security/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Trivy and Kyverno check an image before it runs. Falco watches what the container does after that, syscall by syscall, and alerts when the behaviour doesn&amp;rsquo;t match a rule. This post goes from the one thing Falco does to the config I run, with the noise problem in between.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I scanned my images with &lt;a href=&#34;https://tommeurs.nl/en/posts/trivy-container-scanning/&#34;&gt;Trivy&lt;/a&gt;. I enforced policies with &lt;a href=&#34;https://tommeurs.nl/en/posts/kyverno-policies-governance/&#34;&gt;Kyverno&lt;/a&gt;. My workloads got cryptographic identity through &lt;a href=&#34;https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/&#34;&gt;SPIFFE&lt;/a&gt;. Three layers of prevention, all green, and for a while that felt like enough.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SPIFFE and SPIRE: Zero Trust Service Identity</title>
      <link>https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/</link>
      <pubDate>Sat, 26 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/spiffe-spire-zero-trust/</guid>
      <description>&lt;p&gt;How does Service A know that Service B is actually Service B?&lt;/p&gt;&#xA;&lt;p&gt;I keep coming back to that question because the usual answer is uncomfortable. For years we trusted network location. Traffic from the right IP was legitimate, end of story. Zero trust took that assumption out back and shot it. Now every service has to prove who it is, every single request, no matter where it sits on the network.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kyverno Policies: Governance as Code for Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/kyverno-policies-governance/</link>
      <pubDate>Mon, 14 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/kyverno-policies-governance/</guid>
      <description>&lt;p&gt;I used to keep a wiki page titled &amp;ldquo;Cluster conventions&amp;rdquo;. Resource limits on everything. No &lt;code&gt;:latest&lt;/code&gt; tags. No deploys in the &lt;code&gt;default&lt;/code&gt; namespace. It was a good page. Nobody read it. Six months in, half the cluster broke those rules and I only found out when something fell over.&lt;/p&gt;&#xA;&lt;p&gt;A rule that lives in a doc is a suggestion. A rule the API server refuses to accept is governance. That gap is the whole reason this post exists.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vault for Beginners: Secrets Management in Kubernetes</title>
      <link>https://tommeurs.nl/en/posts/vault-beginners-kubernetes/</link>
      <pubDate>Wed, 02 Jul 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/vault-beginners-kubernetes/</guid>
      <description>&lt;p&gt;The first time I ran &lt;code&gt;kubectl get secret myapp -o yaml&lt;/code&gt; and base64-decoded the value, I felt my stomach drop. There was my database password, sitting in etcd, readable by anyone who could reach the API with the right RBAC. Kubernetes Secrets are not secrets. They&amp;rsquo;re base64-encoded plain text with a fancy name. That&amp;rsquo;s the default, and it&amp;rsquo;s the thing nobody warns you about on day one.&lt;/p&gt;&#xA;&lt;p&gt;Every cloud provider has a fix for sale. AWS has Secrets Manager, Google has Secret Manager, Azure has Key Vault. They work. The catch shows up later: the day you need to migrate, the day you want to know exactly what happens to a secret after you write it, the day you realise your most sensitive data lives in a system you can&amp;rsquo;t inspect.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Progressive Delivery with Argo Rollouts: Canary and Blue-Green Deployments</title>
      <link>https://tommeurs.nl/en/posts/argo-rollouts-progressive-delivery/</link>
      <pubDate>Fri, 20 Jun 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/argo-rollouts-progressive-delivery/</guid>
      <description>&lt;p&gt;A standard Kubernetes Deployment had served me well for a long time. Push a new image tag, watch the pods roll, done. It was simple, it was declarative, and most of the time nothing went wrong. The rolling update even gave me a warm feeling of safety: old pods only get torn down once new ones are ready.&lt;/p&gt;&#xA;&lt;p&gt;That feeling is a lie. A rolling update protects you from pods that fail to start. It does nothing to protect you from pods that start perfectly and then serve broken responses. The container is healthy, the readiness probe is green, and your new code is quietly returning 500s to every single user. Within seconds, 100% of your traffic is hitting code that nobody validated under real load.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Container Image Scanning with Trivy in Your CI Pipeline</title>
      <link>https://tommeurs.nl/en/posts/trivy-container-scanning/</link>
      <pubDate>Sun, 08 Jun 2025 10:00:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/trivy-container-scanning/</guid>
      <description>&lt;p&gt;Pull a base image, copy in your code, push it to production. That&amp;rsquo;s the loop most of us run on autopilot. The part nobody looks at is the base image itself, which quietly drags in a few hundred packages you never chose. Any one of them could carry a known &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;Common Vulnerabilities and Exposures: the public identifier for one specific vulnerability, in the form CVE-2026-1234. The identifier says nothing about severity.&#34;&gt;CVE&lt;/span&gt;&#xA;, and you&amp;rsquo;d have no idea.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Automating Semantic Versioning with GitLab CI</title>
      <link>https://tommeurs.nl/en/posts/semantic-versioning-gitlab/</link>
      <pubDate>Tue, 27 May 2025 19:44:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/semantic-versioning-gitlab/</guid>
      <description>&lt;p&gt;Picture the end state first. You merge a branch to main, walk away to get coffee, and by the time you&amp;rsquo;re back the project has a new version tag, a fresh changelog entry, and a GitLab release with notes written from your commits. Nobody decided &amp;ldquo;is this 1.4.0 or 1.3.5?&amp;rdquo; because nobody had to. The version fell out of the work itself.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s where I want to get to in this post. I run a self-hosted GitLab and I do not want versioning to be a thing I think about. A version number that someone picks by hand is a tiny black box: it depends on whether that person remembered the rules, was paying attention, and agreed with everyone else about what counts as a breaking change. I would rather the number be a consequence of the commits, something I can inspect and reproduce.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GitLab CI for Kubernetes: From Commit to Deployment</title>
      <link>https://tommeurs.nl/en/posts/gitlab-ci-kubernetes/</link>
      <pubDate>Thu, 15 May 2025 20:33:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/gitlab-ci-kubernetes/</guid>
      <description>&lt;p&gt;For a long time my CI lived on someone else&amp;rsquo;s servers. Push code, wait for a hosted runner, watch the minutes tick down against a monthly quota, hope the provider doesn&amp;rsquo;t change the rules next quarter. It worked, right up until I started asking where my source code actually sat while it was being built, and who else could see it.&lt;/p&gt;&#xA;&lt;p&gt;So I moved GitLab in-house. I run it self-hosted now, on my own hardware, next to the clusters it deploys to. That&amp;rsquo;s &lt;a href=&#34;https://tommeurs.nl/en/posts/sovereign-infrastructure/&#34;&gt;sovereignty&lt;/a&gt; applied to CI/CD: my code, my builds, my artifacts, no vendor that can change pricing, deprecate a feature I depend on, or read my repositories without me knowing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Drift Detection with ArgoCD: How to Know If Your Cluster Is Still in Sync</title>
      <link>https://tommeurs.nl/en/posts/argocd-drift-detection/</link>
      <pubDate>Sat, 03 May 2025 19:27:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/argocd-drift-detection/</guid>
      <description>&lt;p&gt;The whole pitch of GitOps is that Git is the source of truth. That promise holds right up until someone runs &lt;code&gt;kubectl edit&lt;/code&gt; on a deployment at 2am to stop an incident, a mutating webhook quietly rewrites a resource, or a half-finished sync leaves your cluster somewhere between what Git wanted and what it got. Now Git says one thing and the cluster does another, and nobody told you.&lt;/p&gt;&#xA;&lt;p&gt;That gap is configuration drift, and it is the part of GitOps people forget to defend. The good news: &lt;a href=&#34;https://argo-cd.readthedocs.io/&#34;&gt;ArgoCD&lt;/a&gt; already watches for it. The catch is that the defaults don&amp;rsquo;t do what you probably assume, and a few of them will bite you. This post walks from the simplest possible drift check up to the setup I actually run, one layer at a time. Stop wherever you have enough.&lt;/p&gt;</description>
    </item>
    <item>
      <title>App-of-Apps Pattern in ArgoCD: Scalable GitOps Architecture</title>
      <link>https://tommeurs.nl/en/posts/argocd-app-of-apps/</link>
      <pubDate>Mon, 21 Apr 2025 20:18:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/argocd-app-of-apps/</guid>
      <description>&lt;p&gt;My homelab started with one ArgoCD Application. Then a handful. The day I caught myself running &lt;code&gt;kubectl apply -f&lt;/code&gt; for the fifteenth time to register yet another Application, I knew I&amp;rsquo;d built the exact thing I was trying to avoid: manual steps I had to remember, in an order I had to remember, with no record of what should exist.&lt;/p&gt;&#xA;&lt;p&gt;The App-of-Apps pattern fixes that with one idea. You create a single root Application by hand, and it creates everything else. After a cluster wipe I can rebuild the whole thing with one &lt;code&gt;kubectl apply&lt;/code&gt;. That property is the entire reason I run it, and it&amp;rsquo;s the same reason I self-host in the first place: I want the repository to be the truth, not my memory.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GitOps Disaster Recovery: Rebuilding Your Cluster from Git</title>
      <link>https://tommeurs.nl/en/posts/gitops-disaster-recovery/</link>
      <pubDate>Wed, 09 Apr 2025 19:52:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/gitops-disaster-recovery/</guid>
      <description>&lt;p&gt;For a couple of years my homelab cluster ran without much drama. Nodes came and went, workloads shifted around, and the worst I ever had to deal with was the occasional pod stuck in &lt;code&gt;CrashLoopBackOff&lt;/code&gt;. The kind of stable where you stop thinking about what happens if it all goes away.&lt;/p&gt;&#xA;&lt;p&gt;Then one evening I ran a &lt;code&gt;terraform destroy&lt;/code&gt; against the wrong workspace. By the time I noticed, the control plane was gone. Not degraded. Gone.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ArgoCD vs Flux: When to Choose What</title>
      <link>https://tommeurs.nl/en/posts/argocd-vs-flux/</link>
      <pubDate>Fri, 28 Mar 2025 21:33:00 +0200</pubDate>
      <guid>https://tommeurs.nl/en/posts/argocd-vs-flux/</guid>
      <description>&lt;p&gt;&amp;ldquo;Should I use ArgoCD or &lt;span class=&#34;def&#34; tabindex=&#34;0&#34; data-def=&#34;The other GitOps engine next to ArgoCD. Controllers in the cluster reconcile from Git with no UI of its own, where ArgoCD leads with one.&#34;&gt;Flux&lt;/span&gt;&#xA;?&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;I get this question over coffee, in Slack, in PR comments, probably once a week. People want me to declare a winner so they can stop thinking about it and go build something.&lt;/p&gt;&#xA;&lt;p&gt;Here is my bias, up front, so you can weigh everything that follows: I run ArgoCD on my own clusters. I have a few years of it under my belt and I like it. That preference is going to leak through no matter how careful I am, so I am telling you now instead of pretending I am neutral.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ArgoCD for Beginners: Your First GitOps Deployment</title>
      <link>https://tommeurs.nl/en/posts/argocd-beginners/</link>
      <pubDate>Sun, 16 Mar 2025 19:15:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/argocd-beginners/</guid>
      <description>&lt;p&gt;Here is the thing I never want to do again: ask a cluster what it is running and not trust the answer. For years that was normal. Someone ran &lt;code&gt;kubectl apply&lt;/code&gt;, maybe from a laptop, maybe from a CI job nobody could find anymore, and the live state slowly drifted away from anything written down. When I switched to GitOps, that whole category of uncertainty disappeared. I push to Git, and the cluster converges to match. If I want to know what is deployed, I read a file.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Running Kubernetes Offline: Edge Computing Without Internet</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-offline-edge/</link>
      <pubDate>Tue, 04 Mar 2025 20:47:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-offline-edge/</guid>
      <description>&lt;p&gt;What happens when your Kubernetes cluster can&amp;rsquo;t reach the internet? I don&amp;rsquo;t mean a slow connection. I mean no connection at all. Ships at sea. Remote mining sites. Factory floors with air-gapped networks. Military deployments.&lt;/p&gt;&#xA;&lt;p&gt;For a lot of people that sounds exotic, like a problem someone else has. I treat it as a baseline design requirement, and I&amp;rsquo;ll explain why it makes my homelab better even though I almost never actually pull the cable.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Graceful Degradation in Kubernetes: What Happens When Components Fail</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-graceful-degradation/</link>
      <pubDate>Thu, 20 Feb 2025 14:22:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-graceful-degradation/</guid>
      <description>&lt;p&gt;Everyone repeats the line that Kubernetes is self-healing. Pods die, they come back. Nodes drop, workloads reschedule. The system reconciles itself toward the state you declared, and most days you never have to think about it.&lt;/p&gt;&#xA;&lt;p&gt;Then one day the thing doing the healing is the thing that broke. The API server is down. etcd won&amp;rsquo;t respond. The scheduler is wedged. Now what?&lt;/p&gt;&#xA;&lt;p&gt;This is the question I actually care about, because &amp;ldquo;self-healing&amp;rdquo; is only useful if I understand its edges. I want to know what degrades gracefully and what takes the whole cluster with it. So I&amp;rsquo;ve run my clusters through a lot of failures on purpose: planned, unplanned, and a few &amp;ldquo;hold my beer&amp;rdquo; experiments on hardware I didn&amp;rsquo;t mind losing. Here is what actually happens when each piece breaks, and why most of it matters less than people fear.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes Network Policies: A Visual Guide to Pod Security</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-network-policies-visual/</link>
      <pubDate>Sat, 08 Feb 2025 19:34:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-network-policies-visual/</guid>
      <description>&lt;p&gt;Picture this: an attacker pops a single pod in your cluster, maybe through a vulnerable image or a leaked token. From that one foothold, they can reach every database, every internal API, every secret-fetching sidecar you run. Nothing stops them, because by default nothing tries to.&lt;/p&gt;&#xA;&lt;p&gt;Network Policies are the thing that stops them. They turn &amp;ldquo;one compromised pod&amp;rdquo; into &amp;ldquo;one compromised pod, and that&amp;rsquo;s it.&amp;rdquo; Everyone knows they should use them. Almost nobody actually does, because the YAML looks scary and the behaviour is weird until the mental model clicks.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How etcd Actually Works: The Heart of Your Kubernetes Cluster</title>
      <link>https://tommeurs.nl/en/posts/etcd-deep-dive/</link>
      <pubDate>Mon, 27 Jan 2025 21:47:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/etcd-deep-dive/</guid>
      <description>&lt;p&gt;When something goes wrong in Kubernetes, the trail usually leads back to etcd. API server timing out? Check etcd. Pods stuck in pending? Might be etcd. Cluster feels sluggish? Probably etcd.&lt;/p&gt;&#xA;&lt;p&gt;For a long time I treated etcd the way most operators do: as a black box that hums along next to the control plane. &amp;ldquo;The database.&amp;rdquo; You back it up and otherwise leave it alone. But black boxes feel like splinters to me, and the first time an etcd cluster fell over at 2am I realised I had no idea what I was actually looking at. So I learned. And it turns out the whole thing is built on a handful of ideas that, once they click, make most etcd problems diagnosable instead of terrifying.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes High Availability: Stacked vs External etcd Explained</title>
      <link>https://tommeurs.nl/en/posts/kubernetes-high-availability-etcd/</link>
      <pubDate>Wed, 15 Jan 2025 20:23:00 +0100</pubDate>
      <guid>https://tommeurs.nl/en/posts/kubernetes-high-availability-etcd/</guid>
      <description>&lt;p&gt;The first &amp;ldquo;production&amp;rdquo; Kubernetes cluster I ran had a single control plane node. It hummed along happily for weeks, right up until a disk failed and took the whole thing with it. Every pod, every service, gone. That outage taught me what &amp;ldquo;single point of failure&amp;rdquo; actually feels like, and it pushed me toward a question that I keep seeing trip people up: when you build a cluster that survives node loss, do you run etcd on your control plane nodes, or on dedicated nodes of its own?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Archive</title>
      <link>https://tommeurs.nl/en/archive/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tommeurs.nl/en/archive/</guid>
      <description>archives</description>
    </item>
    <item>
      <title>Search</title>
      <link>https://tommeurs.nl/en/search/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tommeurs.nl/en/search/</guid>
      <description></description>
    </item>
    <item>
      <title>Start here</title>
      <link>https://tommeurs.nl/en/start-here/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tommeurs.nl/en/start-here/</guid>
      <description>&lt;p&gt;I wrote most of what is here the week the problem turned up, so the archive runs in date order, and date order helps nobody who is starting out.&lt;/p&gt;&#xA;&lt;p&gt;Three paths below. Each one begins at nothing and ends at something running. Pick the one that sounds like your week and ignore the other two.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;entry-paths&#34; data-entry-paths=&#34;3&#34;&gt;&#xA;  &lt;section class=&#34;entry-path&#34; data-entry-path=&#34;linux-desktop&#34;&#xA;    data-entry-path-order=&#34;1&#34; data-entry-path-posts=&#34;5&#34;&#xA;    data-entry-path-first=&#34;/en/posts/linux-is-for-everyone/&#34;&gt;&#xA;    &lt;h2 class=&#34;entry-path-question&#34;&gt;I want off Windows&lt;/h2&gt;&#xA;    &lt;p class=&#34;entry-path-promise&#34;&gt;Ends with Linux as your everyday desktop, and a setup that survives the next reinstall.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
