Check out FlakeHub — the best place to discover and publish Nix flakes, from Determinate Systems.

Sign up for the Determinate Systems mailing list

* indicates required

NixOS

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

Concepts / NixOS

We recommend starting with the Nix quick start and consulting concept docs primarily for clarification. Feel free to click x to the right to disable this notification on all concept docs.

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:

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:

Rebuild your NixOS system
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 = {};
}
Why does my configuration.nix look different?

When you first have a look at NixOS you will undoubtedly see a configuration.nix file in /etc/nixos/. Furthermore, if you look at other people’s NixOS configurations, you might not see this exact structure.

For one, the input set can be shortened (in the most extreme case to just { ... }). See the Nix syntax section for details on what this does.

Additionally, there is some syntactic sugar around NixOS modules, which allow you to omit the config key, if your module does not declare any options. As an example, these two modules are equivalent to each other.

# Module 1
{ ... }:
{
imports = [ ./my-fish-config.nix ];
programs.fish.enable = true;
}
# Module 2
{ ... }:
{
imports = [ ./my-fish-config.nix ];
config = {
programs.fish.enable = true;
};
}

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?