I consider myself a medium-skilled person when it comes to self-hosting and maintaining a home lab. My setup is growing as I try more things, but it is also getting a lot harder to manage. You could blame that on my limited skills, the complexity of the tools, or both. Either way, it pushed me to explore ways to make the system immutable.
I want to be able to rebuild servers identically across hardware, track every change, try things without the fear of breaking anything, and most importantly, add and manage more nodes easily as the home lab grows. It might sound ambitious, but NixOS actually made all of this possible.
NixOS treats your system configuration as code. You can define the entire setup in a single declarative file called configuration.nix. This includes packages, services, users, networking, and even kernel settings. Once defined, the system becomes reproducible, version-controlled, and roll-backable, if that's even a word.
Start by declaring everything in Nix
And enable flakes
As I mentioned earlier, NixOS is a declarative operating system. This means the entire system, including packages, services, users, and even kernel settings, is configured through a single file called configuration.nix or through a flake-based setup.
The first thing I did to make my home lab immutable was capture every aspect of my machines. This includes things like the Nginx setup, user SSH keys, and hardware modules. I wrote all of it as code and stored it in Git. Once that is in place, the reproducibility bit is taken care of.
To take it further, I enabled Flakes. Flakes allow for fully reproducible and locked configurations. They let you pin your system to a specific version of Nixpkgs, so you get consistent builds every time. They also make it easy to define multiple NixOS machines in a single repository, which works well for a home lab setup.
At this point, it also makes sense to disable imperative installs. For anyone unfamiliar, imperative installs are when you manually install packages on a running system using:
nix-env -iA nixpkgs.package-nameThese installs change your user environment outside of your NixOS configuration. They are not tracked in version control and often lead to configuration drift. That completely defeats the purpose of immutability. Instead of using nix-env, declare all your packages in your system configuration. You can enforce this by removing the nix-env binary or by locking down the user environment.
Use nixos-rebuild for atomic changes
Separate runtime state from system configuration
I always use nixos-rebuild for building and applying changes. This tool evaluates your system configuration, builds a new system generation, and then activates it. The whole process is atomic and transactional.
In other words, when you want to change your system (like adding software, turning on a service, or changing a setting), you don’t do it live. Instead, you edit your configuration file and run a single command (nixos-rebuild) to apply the changes.
This applies all changes at once, doesn’t affect the current system until it’s ready, and creates a backup automatically, so you can roll back if something breaks.
The next step in making my home lab immutable was to separate runtime state from system configuration. In an immutable setup, the declarative configuration, which defines what services run, which users exist, and what packages are installed, should be completely isolated from the runtime state, such as database contents, user uploads, logs, and media files.
This approach allows you to treat the system as disposable infrastructure that can be redeployed, upgraded, or rolled back without risking any production data. It aligns with the principles of containerization and infrastructure as code, where services are stateless and storage is stateful.
In a home lab, this separation means you can fully automate the re-provisioning of nodes, restore services quickly on new hardware, maintain reliable backups by keeping data separate from the operating system, and reduce the impact of misconfigurations or failed updates.
NixOS makes managing a home lab easier
It gives you more flexibility

Using NixOS for immutability has changed how I operate my home lab on a daily basis. Every change to the system now goes through updates to configuration files. This leads to well-documented changes, complete with commit history, and helps avoid the classic problem where something works on one machine but not on another. For example, when I wanted to enable a service like Nextcloud or set up a reverse proxy, I added it to the configuration. I activated it across multiple machines in one go.
If I need to apply an update or a security patch across the entire setup, I simply update the version in my Nix expressions and rebuild each machine’s configuration. Because NixOS is designed for consistency and idempotency, every rebuild produces the expected result, no matter the hardware.
NixOS is a lifesaver
NixOS is one of the most exciting Linux distros I have used in years, and I, in fact, consider it one of the best Linux distros out there. It is especially helpful if you’re looking for a distro to reduce the headache of updates and to configure auto-updating. While you’re at it, check out these five amazing Linux distros that are better than Windows.