The Machine That Runs Whether I Remember Setting It Up or Not

I deployed my PDS while drunk.

I know this because I woke up the next morning with absolutely no recollection of doing it, then checked the commit history and found that it was, in fact, running. There's a Bluesky post timestamped during what must have been the middle of it all:

Followed, shortly after, by:

This is, I think, as honest a starting point as any for writing about my experience with NixOS. It's a system that rewards being methodical and principled about how you manage your infrastructure. And I deployed the first major service on it whilst sleep-deprived and slightly inebriated, on a 2021 Dell Inspiron 3501, running over WiFi, from my bedroom.

It still worked. Somehow, it still worked.

The Actual Setup

The server is nothing impressive by any objective measure. It's an old laptop pressed into service — the kind of thing you keep meaning to repurpose and eventually do, at 01:00 in the morning, for reasons that seem compelling at the time. Storage lives on a 2TB Crucial X9 SSD mounted at /srv, which is where all the actual data sits: the PDS, the Forgejo instance, the Nextcloud, the bits and pieces I keep adding every time I decide something else should be self-hosted.

The whole thing is managed by a NixOS configuration that lives in a Git repo. That repo has, at time of writing, accumulated 346 commits. Some of those commit messages are informative. Some of them say things like "fix: why was this not working" and "chore: tidy things I did at midnight." The ratio is roughly what you'd expect.

I got into NixOS partly for the same reasons everyone does — reproducibility, the appeal of having your system described entirely in code, the ability to roll back — and partly because I'd accumulated the kind of configuration debt that accumulates on any system you've been casually managing for long enough. Bits installed here, files edited there. The machine worked, but I couldn't confidently rebuild it from scratch. That bothered me.

NixOS promised the opposite of that. I believed it. The belief was mostly correct, with caveats.

The Learning Curve

There's a point in learning NixOS where you post something like

I know this happens because I have that post in my own archive, timestamped the 18th of February. I know I didn't actually give up because, later that same day, I posted

alongside a screenshot of the PDS running.

That's roughly what the learning curve feels like: not a smooth ascent, but a sequence of walls you hit, recover from, and then scale. The Nix language is a functional, lazily-evaluated expression language, which is a sentence that means something quite specific to the people who know what those words mean and very little to anyone else. If you haven't worked with that paradigm before, you'll spend a while staring at errors that are — in retrospect, once things have clicked — completely legible, and having no idea what they're telling you.

It clicks, though. There was a specific moment, which I can't precisely date, where I stopped reasoning through the Nix module system consciously and started just… knowing what it wanted. Before that moment: painful. After that moment: genuinely enjoyable.

The module system is worth singling out because it's where most of the early frustration lived. Options nest. Attributes merge. Things that look like they should conflict don't, and things that look compatible sometimes aren't. Once you understand the rules, it's elegant. Getting to that understanding involved me going around in circles at least once, losing a secret key at one point (it happens), and posting this:

to Isabel, who was extraordinarily patient with me throughout all of this. Thank you again, Isabel.

What It Actually Gives You

Here's the thing I keep coming back to: the config file is the documentation.

When I set up the AT Protocol PDS, I didn't write a setup guide or make notes. I wrote the Nix configuration. When I set up Forgejo, same. When I set up Nextcloud. All of it is declarative, all of it is in the repo, all of it is readable by future-me without any prior knowledge of what past-me was thinking. The commit history fills in the gaps: you can see exactly what changed, when, and — if I wrote a commit message with any care at all — why.

This sounds like a modest benefit until you've experienced the alternative. "How was this configured? When did this change? Why does this service behave like this?" These are questions I used to have no good answer to on older systems. Now the answer is always "go and read the config." Sometimes it's embarrassing what the config reveals — midnight changes, temporary hacks that outlasted their purpose, an option named something slightly different to what I expected — but at least it's legible. At least it's there.

The rollback system is the other thing I've come to rely on more than I expected to. I've done a significant refactor of the whole configuration structure — more than once, actually — and the worst outcome any of those ever produced was a failed build and the system sitting quietly on the previous generation while I worked out what I'd got wrong. That's not a small thing. That's the difference between "this is a bad afternoon" and "this is a disaster."

It changes how willing you are to experiment. When you can always go back, you're more likely to try things. Which means the config stays intentional instead of calcifying.

The Bits That Are Genuinely Annoying

I don't want to be one of those NixOS people who acts like it's simply better in every way and anyone who finds it difficult just isn't clever enough. That framing is annoying and also not quite true.

Some software is a pain to run on NixOS. Things that assume they can write to arbitrary paths, things that ship their own bundled dependencies, things where the NixOS module doesn't exist yet and you're bodging something together with

extraConfig and stack overflow posts from 2022. The ecosystem has improved significantly, but "significantly" doesn't mean "completely." You'll still hit edges.

Flakes — the more structured, more reproducible way of managing Nix projects — are officially experimental. They've been officially experimental long enough that this designation has started to feel somewhat ceremonial. They work. I use them. But "experimental" means the documentation has gaps, the interface has changed under people more than once, and any advice you find online needs its timestamp checked before you trust it.

Secrets management also deserves a mention. I use agenix for anything sensitive — API keys, credentials, the things that shouldn't live in a public Git repo. It integrates well enough once configured, but "once configured" is doing a lot of work in that sentence. Getting there involved losing a key once, going around in circles at least once more, and eventually arriving at something that works and that I would now describe as "straightforward," purely because I've forgotten how non-straightforward it was to set up.

And then there's the garbage collection. Old generations of the system are kept around by default, which is fine and good and useful right up until you're staring at a disk usage readout wondering where seventy gigabytes went. The answer is always the same. The answer does not stop being surprising.

The Plan, Eventually

The Inspiron 3501 isn't the final home for this. Eventually — when the budget allows — it's moving to a Raspberry Pi, hardwired into the router rather than running over WiFi, which will fix the low-grade anxiety I have every time the network hiccoughs slightly and I wonder briefly if the PDS is still up.

It's funny, in a way. I'm planning a migration that I know will work because I'm running NixOS — I can just swap the hardware configuration, point it at the same external drive, and rebuild. The data's on the SSD. The config's in the repo. The only thing that needs replacing is the machine itself.

That's the whole point, really. That's the pitch made real: the config is the server and the server is wherever you deploy it. The specific hardware is just a detail.

I haven't fully internalised this yet. The Inspiron is still sitting on the shelf above my head as I write this, and there's something faintly surreal about knowing that this account's data is literally within arm's reach. But the knowledge that moving it is an afternoon's work rather than a nightmare project — that part has settled into how I think about infrastructure.

Whether I'd Go Back

No.

The appeal of a system I can reason about completely, where nothing is mystery and everything is legible, turns out to outweigh quite a lot of friction. Especially for something running quietly in the background, doing useful things, being silently depended upon. I don't want surprises from my server. I want it to do what the config says, and I want the config to say what I meant.

The philosophical shift that NixOS requires — configuration as code, state as something to be explicit about, reproducibility as an actual goal rather than a nice-to-have — isn't universally accepted even now. Some people find it overwrought. I understand why. It makes some things harder, at least initially.

But the short-term harder is a one-time cost. The long-term cleaner keeps paying off. Every refactor is easier than the last one. Every new service benefits from everything the previous ones taught you about how to structure things.

And sometimes you wake up to find you deployed it while drunk, and it just… works. Which is either a testament to the system's robustness, or a sign that past-you was more competent at 02:00 than present-you would like to believe.

Possibly both.

The config is publicly available , if you'd like to see what 346 commits of incremental improvement (and the occasional midnight mistake) actually looks like. Some of it is quite good. Some of it was written while tired. The commit messages will tell you which is which.