nixos-basics.md

NixOS configuration

Before this, you'll want

  1. Named function inputs
NixOS18 min

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.

Nix describes instead of instructing

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:

nix replevaluated as you typeNixA plain Nix expression. Nothing from nixpkgs or a module system is supplied.

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.

NixOS understands configuration options

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:

configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Options

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.

GoalName the computer "round-table" and enable Firefox.

  • networking.hostName = "round-table"
  • programs.firefox.enable = true
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Types catch mistakes

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.

GoalFix the value so Firefox is enabled.

  • programs.firefox.enable = true
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Option names are checked too. A typo doesn’t silently create a new setting.

GoalFix the misspelled Firefox option.

  • programs.firefox.enable = true
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Some options have fixed choices

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.

GoalSet the CPU governor to powersave.

  • powerManagement.cpuFreqGovernor = "powersave"
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Where packages come from

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.

GoalInstall Git and Vim system-wide.

  • environment.systemPackages has pkgs.git, pkgs.vim
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Nested paths can be grouped

These two shapes mean the same thing:

NixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.
{
  programs.firefox.enable = true;
  programs.firefox.languagePacks = [ "uk" ];
}
NixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.
{
  programs.firefox = {
    enable = true;
    languagePacks = [ "uk" ];
  };
}

Group settings when it makes the configuration easier to read.

GoalEnable Firefox and add the Ukrainian language pack.

  • programs.firefox.enable = true
  • programs.firefox.languagePacks includes uk
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Users are configuration too

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.

GoalCreate a normal user named me and add it to wheel.

  • users.users.me.isNormalUser = true
  • users.users.me.extraGroups includes wheel
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

One value to leave alone

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.

GoalRecord that this machine began on NixOS 26.05.

  • system.stateVersion = "26.05"
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

Build a small computer

Put the pieces together. Nothing here changes your real machine, so experiment.

GoalFinish the machine so every requirement is satisfied.

  • networking.hostName is "castle-pc"
  • programs.firefox.enable is true
  • networking.firewall.enable is true
  • environment.systemPackages has pkgs.git, pkgs.vim
  • system.stateVersion is "26.05"
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

What to keep

  • 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.stateVersion is set once and then left alone.

Useful links

NORMALCOURSE IN BETA