Your operating system as code
NixOS is a declarative Linux distribution. Instead of manually installing packages and configuring everything individually, you describe the state you want your system to have.
../
.git/
hosts/
modules/
flake.lock
flake.nix
Rather than:
- install a package
- tweak settings
- forget what you changed six months later
you write your configuration and let NixOS build it. Here's a small snippet;
{ self, inputs, ... }:
let
username = "ben";
hostname = "desktop";
addr = "${username}@${hostname}";
system = "x86_64-linux";
systemStateVersion = "25.11";
in {
flake.nixosConfigurations.${hostname} = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit hostname username; };
modules = with self.modules.nixos; [
core
openssh
users
programs
discord
{
If you're using flakes, configurations are commonly organised into modules and hosts.
Hosts usually represent individual machines, such as:
- desktop
- laptop
- server
(This is how I'm currently using it. I'm setting up a host for my Raspberry Pi called server.)
Modules allow reusable configuration to be shared between systems.
For example:
- development tools
- Git configuration
- window manager settings
- common packages
An example of my modules, using flake;
{ flake.modules.nixos.programs = { pkgs, ... }: {
programs.firefox.enable = true;
environment.systemPackages = with pkgs; [
git
curl
wget
ripgrep
python3
uv
unzip
nodejs
live-server
home-manager
google-chrome
spotify
arandr
];
}; }
You can keep this configuration in a Git repository and use it across multiple devices.
This means reinstalling your operating system can become much simpler. Pull your configuration, rebuild, and most of your setup comes back automatically.
Rollbacks
One of my favourite parts of NixOS is that changes aren't immediately permanent.
Every rebuild creates a new system generation.
If something breaks:
- select an older generation at boot
- load the previous working configuration
- fix the issue
Compared with manually trying to remember changes on other systems, this feels much safer.
That said, it’s not completely “hands-off”. There is a learning curve, especially when working with tools like Home Manager and multiple hosts.
For example, I once ran a rebuild through a tool setup (using opencode) that targeted the wrong host configuration. This didn’t break the idea of rollbacks, but it did result in inconsistent system state that I had to manually correct.
It was a useful reminder that while NixOS is reproducible, it still depends on correctly structuring and understanding your configuration.
Linux, distributions, and why I ended up here
Moving from Windows to Linux was probably a bigger shift for me than moving between Linux distributions.
Linux pushes you closer to the underlying system. You become more aware of things like:
- file paths
- directory structures
- permissions
- environment variables
- troubleshooting
That can be frustrating at first, but I found that it forced me to understand concepts I had previously taken for granted.
I remember using Visual Studio Code on Windows years ago and having no idea what a path actually was. With Linux, you're much more likely to run into situations where understanding these details matters.
That doesn't mean Linux is automatically better for everyone. But if you're learning development or working heavily with code, there is value in understanding how your environment works.
As for distributions, NixOS stood out to me because of how flexible and reproducible it feels.
Given my current situation, having my development environment defined in code and stored in a Git repository is reassuring. If something happens to one of my devices, I can pull my configuration and rebuild most of my setup without starting from scratch.
../
i3-config/
i3-config-laptop/
nvim-config/
opencode-config/
bash.nix
chrome.nix
default.nix
discord.nix
git.nix
i3.nix
nvim.nix
opencode.nix
tmux.nix
wezterm.nix
xfce.nix
I've even integrated my dotfiles into the setup, keeping configuration in the tools' native formats — things like Neovim using init.lua, or window manager settings living in their own configuration files.
Final thoughts
I’m still early in my experience with NixOS, but it’s already changed how I think about building and maintaining systems.
It’s not perfect, and it does come with a learning curve — especially when you start working with multiple machines, flakes, and Home Manager.
But for me, the trade-off is worth it. Having a reproducible system defined in code feels far more sustainable than manually managing environments across devices.
It’s one of those tools that starts to make more sense the more you use it.