The whole point of NixOS is configuration.nix — one file (or many imported into one) that captures the entire system state. Change it, run nixos-rebuild switch, and the live system reconciles to match. This guide walks through the everyday workflow.
Prerequisites
- A NixOS install (see NixOS Install Basics).
- Comfort editing a
.nixfile in vim or VS Code.
Step 1: The rebuild verbs
| Verb | Effect |
| --- | --- |
| nixos-rebuild switch | Build the new generation, activate it now, set it as default boot. |
| nixos-rebuild test | Build + activate, but do not change the default. Reverts on reboot. |
| nixos-rebuild boot | Build + set as default, but do not activate now. |
| nixos-rebuild dry-activate | Build and show what would change — no changes applied. |
| nixos-rebuild build | Just build (no activation). For CI. |
Daily flow:
sudoedit /etc/nixos/configuration.nix
sudo nixos-rebuild switch
If the result is broken — even unbootable — you can reboot and pick the previous generation from the bootloader menu. Generations are why you stay.
Step 2: Common modules
Enable a web server:
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
virtualHosts."example.sa" = {
enableACME = true;
forceSSL = true;
locations."/" = { proxyPass = "http://127.0.0.1:3000"; };
};
};
security.acme = {
acceptTerms = true;
defaults.email = "ops@example.sa";
};
Enable Postgres:
services.postgresql = {
enable = true;
package = pkgs.postgresql_16;
enableTCPIP = false;
ensureDatabases = [ "skyline" ];
ensureUsers = [{
name = "skyline";
ensureDBOwnership = true;
}];
};
Enable Docker:
virtualisation.docker = {
enable = true;
autoPrune.enable = true;
};
users.users.ops.extraGroups = [ "docker" ];
Open firewall ports:
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
networking.firewall.allowedUDPPorts = [ 51820 ]; # wireguard
Step 3: Generations and rollback
nixos-rebuild list-generations
sudo nixos-rebuild switch --rollback # revert to previous
sudo nix-env --switch-generation 42 # explicit generation
Older generations stay on disk (cheap — they share most of the closure). Garbage-collect occasionally:
sudo nix-collect-garbage --delete-older-than 30d
Step 4: Channels (the package set you build against)
sudo nix-channel --list
sudo nix-channel --add https://nixos.org/channels/nixos-24.05 nixos
sudo nix-channel --update
sudo nixos-rebuild switch --upgrade
nixos-24.05 is a stable branch; nixos-unstable is rolling. For production stay on the stable channel and bump it once per release cycle.
Step 5: Search for a package or option
nix search nixpkgs ripgrep
nix search nixpkgs '^nginx'
For option documentation:
man configuration.nix
# or browse: https://search.nixos.org/options
Step 6: Split the config across files
configuration.nix (entry point):
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./users.nix
./web.nix
./monitoring.nix
];
# ...
}
Each *.nix file is a normal Nix module. Keep users.nix and web.nix short and topical.
Verify
sudo nixos-rebuild dry-activate # what would change?
nixos-rebuild list-generations
systemctl --failed
journalctl -p err -b
Conclusion
Once you internalise the rebuild verbs and the option search, NixOS is faster to operate than imperative distros — every change is a code diff, every rollback is one command, every machine is a checkout away.
Next steps
- Install NixOS first via NixOS Install Basics.
- For Linux fundamentals that transfer to NixOS see Linux file permissions and systemd services.
- For comparable rolling distros see Install Arch Linux.
Comments
0 total · 0 threads