NixOS

A Linux distribution based on the Nix package manager and guided by Nix's core principles

Concepts / NixOS

NixOS is a Linux distribution based on Nix. It's unique amongst distributions because it enables you to use the Nix language to declaratively configure your operating system in a configuration.nix file. And that configurability runs quite deep, including things like the system's boot loader, the filesystem, window managers, kernel modules, services like OpenSSH, and much more.

In addition to being a fundamentally configurable distribution, Nix provides NixOS with a variety of unique features, such as atomic system updates, system rollbacks, and robust multi-user support.

The role of Nix

Everything in a NixOS system is configured using the Nix language and the NixOS module system. Rather than installing packages and setting up your system in an ad-hoc way, you can declare which specific system you'd like to have—networking stack, filesystem, users, and more—and Nix builds the system for you from the ground up, installing all the required packages, providing necessary configuration files, and making other declared changes.

Features

NixOS uses Nix as its package manager rather than APT, dpkg, or any of the other options for Linux. Nix enables NixOS to provide a range of unique features.

Generations

Unlike other Linux distributions, updates to NixOS system state constitute atomic generations with a number. Each time you run nixos-rebuild switch to apply your desired system configuration, Nix increments the generation. One of the core advantages of generations is that you can switch between atomic versions of your system state at will.

Atomic system updates

Any time you change your NixOS configuration, you can apply that configuration by running nixos-rebuild switch. When you do that, NixOS installs or upgrades any packages that need to be installed or upgraded according to your system configuration. And as is always the case with Nix, each package is realised from scratch and stored in the Nix store rather than in directories like /bin or /usr/bin, as on systems that use the Filesystem Hierarchy Standard.

Rollbacks

As with system updates, NixOS enables you to roll your system back to a previous generation using nixos-rebuild switch --rollback. Rollbacks are fully atomic and include packages, system configuration, and anything else specified in the NixOS configuration.

Multi-user support

NixOS doesn't follow the Filesystem Hierarchy Standard, instead using the Nix store for everything, including not just packages but also derivations and other artifacts. This enables NixOS to support an indefinite number of user profiles in an elegant way. Two different users on the same NixOS host can use different versions of Git, for example, because instead of sharing a global git in a location like /usr/bin/git, two different users can use git executables from Nix store paths instead:

  • /nix/store/sglc12hc6pc68w5ppn2k56n6jcpaci16-git-2.38.1/bin/git
  • /nix/store/8nwsswymka208dpmsy09aydgffvg4bbi-git-2.38.0/bin/git

Below is a diagram of the first path above:

        
/nix/store/ 1. Nix store prefix
sglc12hc6pc68w5ppn2k56n6jcpaci16 2. Hash part
-
git-2.38.1 3. Package name
/
bin/git 4. Program path

Let's break store paths down into their constituent elements:

  1. The root path is /nix/store by default.
  2. The hash is derived from the derivation used to build the package.
  3. The package name is an arbitrary slug provided by the package creator.

Configuration

With most Linux distributions, you assemble your desired system in a procedural way using shell scripts and ad-hoc commands like apt-get install. By contrast, NixOS enables you to define your desired system using the Nix language. By default, this is in a configuration.nix file stored in /etc/nixos. Here's an example configuration:

/etc/nixos/configuration.nix{ pkgs, ... }: # A pinned version of Nixpkgs passed to the configuration by Nix

{
  # Enable Nix flakes and the unified Nix CLI
  nix.settings = {
    experimental-features = "nix-command flakes";
  };

  # Networking configuration
  networking.hostName = "justme-dev-box";

  # Enable OpenSSH
  services.openssh.enable = true;

  # Root filesystem
  fileSystems."/" = {
    device = "/dev/sda1";
    fsType = "ext4";
  };

  # Create a user
  users.users.justme = {
    isNormalUser = true;
    initialPassword = "changemeplz";
  };

  # CLI tools, language runtimes, shells, and other desired packages
  environment.systemPackages = with pkgs; [
    curl
    jq
    wget
    git
    python
    openssl
    zsh
  ];
}

This command applies the configuration above:

nixos-rebuild switch

No complex shell scripts, no sequence of install or build commands, just a single instruction to build the entire system according to your specifications.

Modules

A module is a piece of Nix code that you can configure to produce configuration. In NixOS, a module is a function that takes an attribute set and returns another attribute set. The basic anatomy of a module can be seen in this code snippet:

/etc/nixos/configuration.nix{ lib, config, pkgs, ... }:
{
  imports = [];
  config = {};
  options = {};
}

How to use modules

First up, you can find modules to use and how to use them via the NixOS module search. Nix modules generally follow the declarative principle, meaning that there's no precise order in which modules are executed. Instead, you describe the desired outcome of a system, which Nix then produces for you.

Following is an example of how to setup and configure the nginx web server.

{ ... }:
{
  services.nginx = {
    enable = true;
    virtualHosts."default" = {
      forceSSL = true;            # Redirect HTTP clients to an HTTPs connection
      default = true;             # Always use this host, no matter the host name
      root = /var/www/my-website; # Set the web root to serve
    };
  };
}

Releases

There are two major NixOS releases per year. Release slugs have the form {year}.{month}, so 22.05 corresponds to May 2022, 20.09 corresponds to September 2020, and so on. Because you configure NixOS using Nix, you can always pin specific packages and dependencies to whichever revisions you like.


Was this page helpful?