Introduction
If you’ve used Linux for more than a year, you know the drill. You spend a weekend tweaking your setup, installing packages, tuning your shell, getting your editor just right. Then six months later, something breaks, or you get a new laptop, and you realize you have no idea how you got your machine into the state it’s in.
I’ve lost count of how many times I’ve forgotten what I installed. I’d open a terminal, run some tool, and think “wait, when did I put this here?” Then came the reinstall days. A fresh Ubuntu install, followed by hours of trying to remember every package, every config tweak, every little fix I’d applied months ago and never wrote down.
There’s a name for this, sort of. People call it configuration drift. Your system slowly turns into something only you understand, and only for as long as you remember what you did. The classic “it works on my machine” isn’t a joke at that point, it’s just a fact of life.
Then I found NixOS, and it genuinely changed how I think about my computer.
I won’t pretend the learning curve isn’t real. It is. The first few weeks felt like relearning Linux from scratch. But looking back, every hour I spent fighting with it was worth it.
What Makes NixOS Different?
The core idea behind NixOS is pretty simple to say and a little harder to internalize: instead of installing software step by step, you describe the state you want your system to be in.
You write configuration files that say “this is what my machine should look like,” and NixOS makes it happen. You’re not clicking through installers or running a dozen commands and hoping you remember all of them next time. You’re describing an end state, and the system builds itself to match it.
This is what people mean by declarative configuration. Almost the entire operating system, from installed packages to system services to user accounts, lives in text files. Not in some hidden state scattered across your filesystem, not in your memory, but in files you can read top to bottom.
The effect of this is bigger than it sounds at first. Reinstalling your whole system stops being a chore. You don’t reinstall packages one by one and hope you remember what you had. You just point NixOS at your configuration and let it rebuild everything, exactly as it was.
Reproducibility
This is the part that actually sold me.
Before NixOS, moving to a new machine meant a slow, annoying process of remembering everything I had installed. Some tool for compiling, some library I needed for one specific project, a handful of CLI utilities I used constantly but never wrote down anywhere.
With NixOS, that whole problem mostly disappears. I clone my dotfiles repo, run a single rebuild command, and I get the exact same environment back. Same packages, same versions, same configuration. Nothing forgotten, nothing undocumented.
It sounds almost too simple, but that’s really it. There’s no guessing about whether I installed something through apt, or downloaded a binary manually, or compiled it from source at 2am and forgot about it. If it’s not in my configuration, it doesn’t exist on my system.
This becomes especially valuable when you switch computers. I’ve set up a new laptop with my full development environment in the time it takes to make coffee. Not because I’m fast, but because the machine does the work, not me.
Flakes
If declarative configuration is what convinced me to try NixOS, Flakes are what convinced me to stay.
Flakes are a way of pinning down exactly what your configuration depends on. Before Flakes, your NixOS config technically worked, but it pulled from whatever version of the package repository happened to be around at the time you built it. That’s fine until it isn’t. Rebuild your system a year later, and you might get different versions of things without meaning to.
Flakes fix this by making your inputs explicit and locked. You declare exactly which sources your configuration depends on, and a lock file records the precise versions being used. Rebuild your system next week, next month, or next year, and you get the same result every time, unless you deliberately update something.
Flakes also just make your project structure cleaner. Instead of configuration spread across a handful of files with unclear relationships, everything has a defined entry point and clear inputs and outputs. It’s much easier to share your setup with someone else, or move it between machines, because the boundaries of what your configuration needs are obvious.
Rebuilding a flake-based system looks like this:
sudo nixos-rebuild switch --flake .#hostname
In plain terms, this tells NixOS to take the flake in your current directory, look up the configuration for the given hostname, and rebuild your system to match it. It builds the new system generation, activates it, and you’re running the updated configuration almost immediately. No reboots needed for most changes, and if something in your flake didn’t change, it just reuses what’s already built.
Before Flakes, I was fine with plain NixOS configuration. After Flakes, I genuinely don’t want to go back to anything less structured.
Home Manager
Configuring the operating system is only half the picture. Your actual day-to-day experience lives in your user environment, not in system services.
I’m talking about Neovim configs, Git settings, shell aliases, terminal preferences, and the specific development tools I reach for constantly. None of that is really “the operating system,” but all of it matters just as much when you’re trying to reproduce your setup.
This is where Home Manager comes in. It takes the same declarative philosophy NixOS applies to the whole system and applies it to your personal environment instead. Your dotfiles, your Neovim plugins, your Git aliases, your shell configuration, all described in the same style of configuration files.
Applying your user environment looks like this:
home-manager switch --flake .#username
Once I set this up, my entire development environment became something I could version control the same way I’d version control a project. Editor config, shell setup, terminal preferences, all tracked in Git alongside my system configuration. Moving to a new machine doesn’t just restore my operating system anymore, it restores me.
Rollbacks
This is the feature that feels a little bit like magic the first time you use it.
Every time you rebuild your NixOS configuration, you’re not overwriting your previous setup. You’re creating a new generation, while the old one stays right there, untouched. So if something goes wrong, whether it’s a broken update, a bad configuration change, or just a mistake you made at midnight, you’re not stuck debugging your way out of it.
You just roll back.
sudo nixos-rebuild switch --rollback
That’s it. Your system goes back to exactly how it was before, with no manual undoing, no trying to remember what you changed, no digging through logs trying to figure out what broke.
Knowing this exists changes how you experiment. I try things on my system now that I would have been way too cautious to attempt before. Worst case, I roll back and I’m exactly where I started, no damage done.
Garbage Collection
Of course, all those generations have to live somewhere. Every rebuild adds a new one, and over time, old generations pile up on your disk.
This is where garbage collection comes in. It’s exactly what it sounds like: cleaning up old, unused generations so they stop taking up space.
sudo nix-collect-garbage -d
Running this clears out old generations and unused packages, freeing up disk space, without touching your current, active system. It’s a nice reminder that rollbacks aren’t free in terms of storage, but cleaning up after yourself is simple and doesn’t put you at any risk.
I run this every so often, mostly when I notice my disk usage creeping up. It takes a few seconds and I don’t think about it again for weeks.
Why I Enjoy Daily Life on NixOS
Here’s the part that’s less about features and more about how it actually feels to use this thing every day.
Updating my system is boring now, in the best possible way. I edit a config file, rebuild, and move on. Nothing surprises me. Every package on my machine is there because I put it there, not because some installer script decided I needed it.
Everything lives in Git. My system config, my Home Manager setup, all of it. I can look at the commit history and see exactly when and why I made a change. That alone has saved me more debugging time than I expected.
There’s less maintenance overhead in general. I’m not chasing down weird dependency issues or wondering why something that worked last week doesn’t work today. When something does break, it’s usually because I changed something, and I know exactly what and where.
Honestly, the biggest shift is just having more mental space to build things instead of maintaining the platform I build them on.
Is NixOS For Everyone?
I want to be honest here, because I don’t think NixOS is the right fit for every developer, and it wouldn’t be fair to pretend otherwise.
The learning curve is real. The Nix language itself takes some getting used to, and package management works differently enough from traditional Linux distributions that some habits you’ve built over years won’t transfer directly. Debugging issues can also feel unfamiliar at first, since errors sometimes point you toward the build system rather than the specific package you’re touching.
If you just want something that works without thinking about how it works, NixOS might frustrate you more than it helps.
But if you’re the kind of person who actually enjoys understanding your tools, who wants to know exactly why your system behaves the way it does, the tradeoff is worth it. The benefits stack up quickly once you get past the initial friction, and they keep paying off the longer you stick with it.
Final Thoughts
NixOS didn’t make me a better developer overnight. I didn’t suddenly write better code or ship faster because I switched operating systems.
What it gave me was confidence. Confidence that my system is exactly what I say it is. Confidence that I can rebuild it anywhere, roll back any mistake, and never again wonder what I installed eight months ago and why.
I no longer think of my operating system as something I install. It’s something I build.