Declare, Don't Manage
There's a system running somewhere that you touched but don't understand anymore.
Maybe it's Kubernetes. Maybe it's a cloud environment with three years of console-applied patches beneath the surface. Maybe it's something smaller — a server configured by a series of SSH sessions nobody documented. You can interact with it. You don't know what it is.
This is what imperative management produces over time: systems you can act on but can't read.
i · the drift problem
Imperative infrastructure has a specific failure mode. You run commands, apply patches, override configs. Each action changes state. The system works — until it doesn't. When it breaks, you're debugging something you didn't design, only accumulated.
The author of nixidy opens with a familiar symptom: a Helm values override file 600 lines long, with no clear picture of which values actually made it into the rendered manifests. The YAML is there. The intent behind it has drifted.
Drift is the gap between what you meant to build and what exists. The imperative approach doesn't make this gap visible — it defers the reckoning. Each command adds sediment. The system accumulates more history than you can hold.
ii · what declaring changes
Nixidy is a tool for managing Kubernetes via Nix expressions. Instead of writing raw YAML or reaching for Helm, you declare your infrastructure as typed Nix modules. The build produces plain YAML you can git diff before anything touches the cluster.
The workflow is deliberately legible:
- Write environment modules expressing what you want
- Build — type errors surface here, not at runtime
- Commit the rendered YAML to version control
- Argo CD deploys the static output
What you get back isn't just automation. It's readability. The full picture of your desired state lives in code. If the running cluster diverges from that code, the divergence is visible. You can audit it, diff it, revert it.
One nginx declaration produces a typed Deployment, a Service, a Namespace, and the Argo CD Application manifest. Unremarkable on its own. What's remarkable is that you can explain exactly what you have and why — because you said it explicitly. Every field is typed. Every build is reproducible. The system you're running is the system you declared.
iii · activity vs. agency
This is the tension worth sitting with: imperative management feels like agency. You're doing things. Applying changes. Making the system behave.
But there's a difference between the ability to act and the ability to see. You can run commands against a system you've lost track of. That's not agency — that's touch without comprehension. Real agency requires knowing the gap between what you want and what exists.
Declarative systems invert this. Instead of patching pods, you state desired state. You give up the illusion of direct control in exchange for something more durable: visibility. The gap between intent and reality becomes explicit. Convergence becomes the system's job. Your job becomes stating your intent clearly enough for the system to enforce it.
This is alignment over force. Not "I pushed this change" but "I expressed this desire and the system maintained it." The surfer doesn't fight the wave — they position where its power becomes useful. You declare the shape of what you want; the infrastructure carries you there.
The upfront cost is real. Learning Nix's module system takes more than an afternoon. Nixidy's author is honest about the tradeoff: that complexity lives in your tools, not your configs. What you're buying is sovereignty — infrastructure you can read, reproduce, and revert. A system legible to the next person, or to yourself six months from now when something breaks at 2am and you need to understand what you actually meant.
iv · managing vs. declaring
Kubernetes is a specific context. The pattern is general.
Anywhere you're managing state imperatively — shell scripts that mutate in place, servers shaped through accumulated SSH sessions, environments where the ground truth is "what's running" rather than "what we said we want" — you have the same problem: systems you can touch but can't fully see.
The test is simple: can you read what you have? Can you state your desired state precisely enough that a diff would show you the gap? If you can't, you're managing. You might want to declare instead.
Start with the audit: pick one system you touch regularly and ask whether you could reconstruct it from its config files alone. The gap you find is where declaring begins.
The cost of declaring is front-loaded. It requires precision about what you actually want before you build it. That precision is also the point: you can't declare what you haven't thought through. The discipline of declaration is the discipline of intent — the practice of knowing what you mean before you act on it.
Build once, audit forever. Declarative infrastructure is a permanent capability. The system becomes legible, portable, and self-documenting. You stop accumulating state you can't explain and start building something you can read.
threaded with
- river · Agency
You Only Own What You Can Still Run
OpenMW just shipped a new engine for a 24-year-old game. The lesson isn’t nostalgia — it’s that you only own what you can still run. Here’s how to tell the difference, and what to do about it.
5 days ago
- river · Agency
The Datasheet Is Not a Deed
AMD quietly killed a security feature on consumer Ryzen chips by flipping one firmware flag. A field guide to finding where the off switch really lives — and choosing what to defend.
1 week ago
- river · Agency
Comprehension as Sovereignty
Choosing tools you can read isn't nostalgia — it's a sovereignty claim. When you understand your stack, you're in a governing relationship with it. When you don't, you have a dependency you haven't named.
3 weeks ago