On a Debian-style system using systemd, you might configure the computer by running commands like these. Other Linux distributions spell them differently.
$ sudo apt install firefoxReading package lists... DoneSetting up firefox...$ sudo hostnamectl set-hostname workstation$ sudo systemctl enable --now sshCreated symlink /etc/systemd/system/sshd.service
Each command changes the current machine. The final system is the result of every command you ran, every file you edited, and every command you forgot you ran six months ago.
The computer works. What it is, though, is the sum of everything that has ever been done to it, and nobody wrote that list down.
NixOS starts from a completely different question. Instead of asking which commands you should run, it asks what value describes the computer you actually want.
This is an ordinary Nix expression:
Evaluation does not install anything. Nix simply works out the resulting attribute set. Building the machine is a separate step. What you wrote is a description of a system, not a sequence of commands to get there.
An attribute set on its own is just data, though. Something has to know that
hostName means the machine’s name, and refuse the ones you invented by accident.
That something is the module system. It is written in Nix itself, it defines every option name you are allowed to use, and it will later let you add options of your own.
This descriptive value becomes a real NixOS configuration when NixOS evaluates it:
Each recognized setting is an option. An option has a name, a description, and a type of value it accepts.
Hover an option in the editor to see its documentation.
Name the computer "round-table" and enable Firefox.
networking.hostName="round-table"programs.firefox.enable=true
programs.firefox.enable expects a boolean. The string
"yes" may sound positive, but it’s still text, and the type checker is not
reading it for tone.
Fix the value so Firefox is enabled.
programs.firefox.enable=true
Option names are checked too. A typo doesn’t silently create a new setting.
Fix the misspelled Firefox option.
programs.firefox.enable=true
The CPU governor accepts four names. Invent a fifth one and you get
an error, not a machine that quietly ignores you. powersave is the one you want
on a laptop that would rather keep its battery money in the bank than win a
benchmark.
Set the CPU governor to powersave.
powerManagement.cpuFreqGovernor="powersave"
A NixOS configuration is often a function. NixOS passes useful inputs into it,
including pkgs, the package set from nixpkgs.
That header at the top is the configuration asking for it by name, and
environment.systemPackages is the list that becomes available to every user on
the machine once you build it.
Install Git and Vim system-wide.
environment.systemPackageshaspkgs.git,pkgs.vim
These two shapes mean the same thing:
{
programs.firefox.enable = true;
programs.firefox.languagePacks = [ "uk" ];
}
{
programs.firefox = {
enable = true;
languagePacks = [ "uk" ];
};
}
Group settings when it makes the configuration easier to read.
Enable Firefox and add the Ukrainian language pack.
programs.firefox.enable=trueprograms.firefox.languagePacksincludesuk
A user account is another group of options, and being in wheel is what grants
permission to use sudo. So this is the line deciding whether you can administer
your own machine. Go grab your crown, king.
Create a normal user named me and add it to wheel.
users.users.me.isNormalUser=trueusers.users.me.extraGroupsincludeswheel
system.stateVersion records the NixOS release this machine was first installed
on. It is there so stateful data keeps working when
everything around it moves on.
So you set it during installation, and then you leave it alone forever. Bumping it because a newer number exists is not an upgrade.
Record that this machine began on NixOS 26.05.
system.stateVersion="26.05"
Put the pieces together. Nothing here changes your real machine, so experiment.
Finish the machine so every requirement is satisfied.
networking.hostNameis"castle-pc"programs.firefox.enableistruenetworking.firewall.enableistrueenvironment.systemPackageshaspkgs.git,pkgs.vimsystem.stateVersionis"26.05"
- A declarative configuration describes the machine you want.
- NixOS options have names, documentation, and expected value types.
- Lists hold repeated values such as packages and groups.
- Related option paths can be grouped into an attribute set.
system.stateVersionis set once and then left alone.


Share your thoughts