<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>codedbearder</title><link>https://codedbearder.com</link><description>Recent content https://codedbearder.com</description><generator>nixtml</generator><language>en</language><atom:link href="https://codedbearder.com/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Mon, 08 Jun 2026 12:30:00 +0000</lastBuildDate><item><title>nixidy part 6: CI integration and the promotion workflow</title><link>https://codedbearder.com/posts/nixidy-part-6-ci-workflow</link><guid>https://codedbearder.com/posts/nixidy-part-6-ci-workflow</guid><pubDate>Mon, 08 Jun 2026 12:30:00 +0000</pubDate><description>&lt;p&gt;Every change we've made so far has been local: edit a Nix file, run &lt;code&gt;nixidy build&lt;/code&gt;, inspect &lt;code&gt;result/&lt;/code&gt;, run &lt;code&gt;nixidy switch&lt;/code&gt; to copy manifests into the repo, commit, push. That workflow works for one person. It breaks the moment a second person needs to review what's being deployed, because they see a Nix diff, not a YAML diff, and they have to trust that &lt;code&gt;nixidy build&lt;/code&gt; produces what they expect.&lt;/p&gt;
&lt;p&gt;The rendered manifests pattern exists to solve this. CI builds the YAML from the Nix files and commits it to a known location in the repository (a promotion branch, a subdirectory on main, or a separate repository entirely). The reviewer sees a plain &lt;code&gt;git diff&lt;/code&gt; of Kubernetes YAML. Argo CD picks up the change and deploys it. The Nix files are the source of truth; the YAML is the review artifact.&lt;/p&gt;
</description></item><item><title>nixidy part 5: Build-time assertions and warnings</title><link>https://codedbearder.com/posts/nixidy-part-5-assertions-and-warnings</link><guid>https://codedbearder.com/posts/nixidy-part-5-assertions-and-warnings</guid><pubDate>Mon, 08 Jun 2026 12:00:00 +0000</pubDate><description>&lt;p&gt;Type checking catches the wrong shape of data: a string where an integer belongs, a missing required field. But it can't catch semantic errors like a production Deployment with zero replicas, a namespace that isn't being created, or two applications that must always be deployed together. These are invariants about the cluster configuration that no schema can express.&lt;/p&gt;
&lt;p&gt;nixidy borrows the NixOS assertion and warning system for exactly this. Assertions are build-time hard constraints: if one fails, the build stops. Warnings are advisory, they print to stderr but don't block the build. Both are evaluated during &lt;code&gt;nixidy build&lt;/code&gt;, before any YAML reaches the repository or the cluster.&lt;/p&gt;
</description></item><item><title>nixidy part 4: Typed resource options and CRD generation</title><link>https://codedbearder.com/posts/nixidy-part-4-typed-resource-options</link><guid>https://codedbearder.com/posts/nixidy-part-4-typed-resource-options</guid><pubDate>Mon, 08 Jun 2026 11:30:00 +0000</pubDate><description>&lt;p&gt;Every Kubernetes resource we've defined so far (Deployments, Services, Ingresses, Namespaces, ConfigMaps) has been typed. We didn't install anything extra to make that happen, nixidy ships with typed options for all core Kubernetes resources, generated from the official JSON schemas. When I write &lt;code&gt;replicas = 3&lt;/code&gt;, the module system checks that &lt;code&gt;3&lt;/code&gt; is an integer. When I write &lt;code&gt;replicas = "three"&lt;/code&gt;, the build fails with a type error naming the exact option and the type it expected.&lt;/p&gt;
&lt;p&gt;That type checking extends beyond built-in resources too. nixidy includes a code generator that produces typed Nix options from any Custom Resource Definition, so my Cilium network policies, cert-manager certificates, and Prometheus service monitors get the same build-time validation as a plain Deployment. This part covers how the built-in types work under the hood, how to generate types from CRDs, and how to handle resources that don't fit the typed model.&lt;/p&gt;
</description></item><item><title>nixidy part 3: Reusable templates for recurring application patterns</title><link>https://codedbearder.com/posts/nixidy-part-3-reusable-templates</link><guid>https://codedbearder.com/posts/nixidy-part-3-reusable-templates</guid><pubDate>Mon, 08 Jun 2026 11:00:00 +0000</pubDate><description>&lt;p&gt;The third time I write a Deployment + Service + Ingress trio I start to notice the shape: selector labels that match the pod template labels, a service port that mirrors the container port, an ingress that references the service by name. Every field is wired to every other field, and a typo in one label breaks the chain silently. By the fifth web application I'm copying an existing module and changing five values and hoping I changed all five.&lt;/p&gt;
&lt;p&gt;nixidy's template system captures that pattern once, with typed options for the variables and an &lt;code&gt;output&lt;/code&gt; function that generates the resources. I can instantiate it with different &lt;code&gt;image&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt;, and &lt;code&gt;replicas&lt;/code&gt; values and get a complete application each time. No duplication, no missed wiring.&lt;/p&gt;
</description></item><item><title>nixidy part 2: Multi-environments and Helm charts</title><link>https://codedbearder.com/posts/nixidy-part-2-multi-env-and-helm-charts</link><guid>https://codedbearder.com/posts/nixidy-part-2-multi-env-and-helm-charts</guid><pubDate>Mon, 08 Jun 2026 10:30:00 +0000</pubDate><description>&lt;p&gt;In &lt;a href="/posts/nixidy-part-1-introduction/"&gt;the previous part&lt;/a&gt; we created a single nixidy application. The nginx &lt;code&gt;Deployment&lt;/code&gt; in &lt;code&gt;dev.nix&lt;/code&gt; is 20 lines. When I add &lt;code&gt;staging.nix&lt;/code&gt; and &lt;code&gt;prod.nix&lt;/code&gt; I'll have three copies of those 20 lines, and they'll be identical except for &lt;code&gt;replicas&lt;/code&gt; and maybe an annotation or two. Change the container port in one, forget it in another, and I've got a silent divergence that no CI check will catch.&lt;/p&gt;
&lt;p&gt;The NixOS module system solves this the same way it solves duplicate NixOS host configs: shared base modules, &lt;code&gt;imports&lt;/code&gt;, and priority primitives that let me express "same app, different scale" in two lines instead of a full file copy. This part covers that composition, then adds a Helm chart to the mix (because most real clusters run at least one piece of software that only ships as a Helm chart).&lt;/p&gt;
</description></item><item><title>nixidy part 1: Introduction to nixidy</title><link>https://codedbearder.com/posts/nixidy-part-1-introduction</link><guid>https://codedbearder.com/posts/nixidy-part-1-introduction</guid><pubDate>Mon, 08 Jun 2026 10:00:00 +0000</pubDate><description>&lt;p&gt;I have managed many GitOps repositories for Kubernetes with ArgoCD and I'm sure I'm not alone in having opened a Helm values override file that was 600 lines of YAML and still not being sure which values actually made it into the rendered manifests. I've run &lt;code&gt;helm template&lt;/code&gt;, piped it through &lt;code&gt;grep&lt;/code&gt;, given up, committed it anyway and hoped the staging diff would catch anything my eyes missed.&lt;/p&gt;
&lt;p&gt;That gap between what you &lt;em&gt;think&lt;/em&gt; you're deploying and what actually lands in the cluster is exactly what &lt;a href="https://github.com/arnarg/nixidy"&gt;nixidy&lt;/a&gt; is meant to close. I wrote it to replace Helm value files, Kustomize overlays, and raw YAML with a single Nix expression per environment. Every field is typed, every build is reproducible, and the output is plain YAML you can &lt;code&gt;git diff&lt;/code&gt; before it ever touches a cluster.&lt;/p&gt;
</description></item><item><title>I made a new backplane for my Terramaster F2-221 NAS</title><link>https://codedbearder.com/posts/f3-backplane</link><guid>https://codedbearder.com/posts/f3-backplane</guid><pubDate>Fri, 26 Apr 2024 13:00:00 +0000</pubDate><description>&lt;p&gt;In a &lt;a href="https://codedbearder.com/posts/nixos-terramaster-f2-221"&gt;previous post&lt;/a&gt; I wrote about how I setup NixOS on my Terramaster F2-221 instead of using the included TOS provided by Terramaster. This in itself was quite simple as the NAS contains Intel J3355, a standard X86_64 CPU. However the NAS only has 2 SATA connectors, both of which were being used for the 4TB hard drives, so I had to resort to plugging in an external USB SSD for storing the operating system. This quickly became a little annoying to make room for this external SSD behind the NAS and make sure it's always plugged in when something is moved around in the shelf where I keep it, so I wanted to see if I could come up with a better solution.&lt;/p&gt;
</description></item><item><title>Making NanoPI R4S booting sane with SPI Flash</title><link>https://codedbearder.com/posts/nanopi-r4s-spi-flash</link><guid>https://codedbearder.com/posts/nanopi-r4s-spi-flash</guid><pubDate>Thu, 04 Apr 2024 16:30:00 +0000</pubDate><description>&lt;p&gt;There's one thing I really don't like about many popular ARM SBCs (Single Board Computers) that for some reason has been deemed acceptable and that is the lack of on-board flash for storing the bootloader. This means that the bootloader (most often u-boot) needs to be written to a specific location on the SD card or eMMC (if available). Generally distributions for such boards offer an image for download that can be written as is to the boot medium, including the bootloader, requiring such images to be created for &lt;em&gt;each supported SBC&lt;/em&gt;. Wouldn't it be nice if we could just pop in a generic installer USB stick where we can partition the drive as needed before installing, like is done with generic x86 computers?&lt;/p&gt;
</description></item><item><title>I wrote a keyboard remapper for wayland</title><link>https://codedbearder.com/posts/writing-keyboard-remapper-wayland</link><guid>https://codedbearder.com/posts/writing-keyboard-remapper-wayland</guid><pubDate>Sat, 11 Apr 2020 17:40:00 +0000</pubDate><description>&lt;p&gt;Recently I bought a new laptop with the intention of running Linux with Sway as my WM. This is the setup I run on my workstation where I have a 60% keyboard on which I use caps lock as a function key for a second layer.&lt;/p&gt;
&lt;p&gt;Because muscle memory is a thing I have been using Karabiner Elements to remap the keyboard on my work macbook pro but I could not find a suitable alternative for Linux when using a Wayland compositor.&lt;/p&gt;
</description></item><item><title>Running NixOS on a consumer NAS</title><link>https://codedbearder.com/posts/nixos-terramaster-f2-221</link><guid>https://codedbearder.com/posts/nixos-terramaster-f2-221</guid><pubDate>Sun, 02 Feb 2020 18:00:00 +0000</pubDate><description>&lt;p&gt;I have an old whitebox server sporting a Xeon E5 (v1) that I'd like to get rid of. It's running a handful of VMs on Proxmox. Most of them I can get rid of by moving their services to Kubernetes, but I wasn't sure what I wanted to do with my NAS VM and Plex server. The latter you can easily run in Kubernetes but I'm not planning on having particularly powerful nodes and I need transcoding.&lt;/p&gt;
</description></item><item><title>TX3 Mini: Mainline Linux on an Android TV Box</title><link>https://codedbearder.com/posts/mainline-linux-on-tx3-mini</link><guid>https://codedbearder.com/posts/mainline-linux-on-tx3-mini</guid><pubDate>Tue, 26 Mar 2019 10:00:00 +0000</pubDate><description>&lt;p&gt;I've always found Raspberry Pi cases and the Pi's connector locations to be rather aesthetically unpleasing, with the power connector coming out from the side and the ethernet from the back (or vice versa). Imagine my excitement when I was browsing the &lt;a href="https://github.com/torvalds/linux"&gt;github mirror of Linux&lt;/a&gt; (as you do) and I ran into a dts for an Android TV box called Tanix TX3 Mini.&lt;/p&gt;
</description></item></channel></rss>