The previous post was about what I think Nix is. This one is about how I ended up using it everywhere. I started with nix-darwin, moved the homelab to NixOS, and eventually pulled this blog into the same setup.

Before Nix: Docker and defaults

I was already doing two things that made Nix appealing.

I used Docker for most projects because it gave me a repeatable environment instead of another “it works on my machine” problem. I also spent too much time tinkering with my MacBook, right down to changing settings with defaults commands in the terminal.

Then I found Nix and nix-darwin. They gave me a macOS package manager that could keep those preferences in code. It felt like applying infrastructure as code to the laptop in front of me.

nix-darwin : fenrir, then huginn

At first, it was a fight. Learning the language was hard enough; understanding what Nix was doing under the hood took longer.

Once the model started to click, I moved my config files into Nix. My personal MacBook, fenrir, came first. After I adopted flake-parts and the dendritic pattern, I brought my work MacBook, huginn, into the same declaration.

homelab : Proxmox out, NixOS in

I started the homelab on Proxmox VE, but it felt heavy for a small personal setup running on old hardware. I began reading other people’s NixOS configurations and decided to replace it.

The nixpkgs ecosystem already supported almost every service I wanted to run. More importantly, I was trying to move my career toward infrastructure and DevOps work, and I wanted a place where breaking things was part of the exercise. With NixOS, a bad configuration usually fails during the build, before nixos-rebuild switch touches the running system. That made the homelab a much safer place to experiment.

blog : my own custom flake module

This blog is an Astro project in TypeScript and runs on Bun. Local development is the ordinary bun dev.

Deployment was the interesting part. I wanted the site on one of my homelab nodes, so I wrote a flake module in the blog repository and imported it into the homelab as a flake input.

How the blog reaches the homelab
flowchart LR
subgraph blog [blog repo]
  M[flake module]
end
subgraph lab [homelab repo]
  I[flake input] --> C[node configuration]
end
M --> I
C -->|rebuild switch| N[homelab node]

The first build failed for a useful reason. Bun’s default x86_64-linux binary requires AVX2, which my old homelab CPU does not support. I fixed it with an overlay that swaps in Bun’s baseline build:

dev-with-min-node-modules-0.1.0.drv
error: Cannot build '/nix/store/in3ydhnl8x791vndixidwkr8yinqniiv-dev-with-min-node-modules-0.1.0.drv'.
Reason: builder failed with exit code 132.
Output paths:
/nix/store/ivmcaavvmy4nm2qixkvkmgv0apd0fkmg-dev-with-min-node-modules-0.1.0
Last 7 log lines:
> Running phase: unpackPhase
> unpacking source archive /nix/store/d4bf9lrp9qgjzjy6xw8r4gpbj7nvrqid-source
> source root is source
> Running phase: patchPhase
> Running phase: updateAutotoolsGnuConfigScriptsPhase
> Running phase: buildPhase
> /nix/store/pr27j8nm0xl52pq4ylncj9kwjw3b84mk-stdenv-linux/setup: line 1776: 31 Illegal instruction (core dumped) bun install --frozen-lockfile --ignore-scripts --no-progress --backend=copyfile --os=linux --cpu=x64
overlays.nix
bun =
if prev.stdenv.hostPlatform.system != "x86_64-linux"
then prev.bun
else
# swap the source archive for bun's baseline (non-AVX2) release build
prev.bun.overrideAttrs (old: {
# ...
});

This was exactly the kind of failure I wanted from NixOS. The build told me that the declared system could not run on the target CPU before anything was applied. It also forced me to learn why the binary itself mattered, not just whether a package named bun existed.

What I learned

Nix made declarative configuration concrete for me. I had to compare different module patterns, live with my choices, and work out which ones I could still understand later. I also got much better at finding answers in unfinished documentation and old discussions scattered across open source repositories.

Nix is not mainstream, and I cannot build an infrastructure career around it alone. I still need time with the languages and tools that show up in ordinary DevOps jobs. Even so, Nix suits the way I like to work. It is also the reason I now have a homelab where I can practice the rest.