Overview of the NixOS Linux distribution
NixOS is a Linux distribution based on the Nix Package Manager. It supports reproducible and declarative system-wide configuration management as well as atomic upgrades and rollbacks, although it can additionally support imperative package and user management. In NixOS, all components of the distribution — including the kernel, installed packages and system configuration files — are built by Nix from purely functional (that is, side-effect free) Nix expressions.
Since Nix uses binary caching, this provides a unique compromise between the binary-oriented approach used by distributions such as Debian and the source-oriented approach used by distributions such as Gentoo. Binaries can be used for standard components, and custom-built packages and modules can be used automatically when a prebuilt binary is not available.
Stable NixOS releases are delivered biannually. NixOS was created by Eelco Dolstra and Armijn Hemel, and initially released in 2003. It is community developed and maintained under the stewardship of the NixOS Foundation.
Usage
Installation
For a full installation guide, see the Installation chapter of the NixOS manual.
Most users will install NixOS via one of the ISO images. Both "graphical" and "minimal" ISO variants are available for each supported architecture; the "graphical" images are suitable for users intending to install a desktop environment, and the "minimal" images are suitable for users intending to install NixOS in a server role or desiring a smaller ISO image.
The ISO images are hybrid images which can be burnt to optical media or copied raw to a USB drive and booted as-is. See the installation guide for details.
In addition to the ISO images, the download page provides a number of alternative methods for installing NixOS. These include:
- virtual appliances in OVA format (compatible with VirtualBox);
- Amazon EC2 AMIs;
- Microsoft Azure blobs.
Additionally, many existing Linux installations can be converted into NixOS installations using nixos-infect or nixos-in-place; this is particularly useful for installing NixOS on hosting providers which do not natively support NixOS.
For information on installing NixOS on various ARM devices, see NixOS on ARM.
Declarative Configuration
One of NixOS's most distinguishing features is the ability to declaratively configure the whole system. This is done by specifying a configuration file which specifies the entire system state, including which packages should be installed and all the various system settings and options. This configuration file is normally located at /etc/nixos/configuration.nix
(although another location may be specified using the environment variable NIX_PATH
); after the configuration file is modified, the new configuration is then made active by running nixos-rebuild switch
. The switch is atomic and can be rolled back if necessary. The configuration files under /etc/nixos
may even be kept in a version control system such as Git if desired.
Conventional distributions require users to manually modify configuration files, but these changes are not tracked. If distributions change the default contents of configuration files, these changes often have to be manually merged by users if they have previously modified the file, or the distribution modifications may not be integrated at all, leading to undesired configuration drift. Configuration settings and changes are rarely recorded in a version control system. These shortcomings are often rectified after-the-fact if at all by configuration management solutions such as Puppet or Chef. These tools reconcile system configuration with a description of the expected state. However, these tools are not integrated into the operating system design and are simply layered on top, and OS configuration may still vary where an aspect of OS configuration has not been specified in the description of expected state.
By comparison, NixOS's declarative configuration system provides a fully integrated facility for OS configuration management. Failure to specify any given item of configuration results in that item having a well-defined state, rather than being allowed to drift unmonitored. Because the full system configuration is captured in the NixOS configuration system, this also makes NixOS highly suited to the automatic deployment of configuration in environments such as automated server farms; tools such as NixOps make this easy.
The following is an example /etc/nixos/configuration.nix
:
{ config, pkgs, ... }:
{
# Import other configuration modules
# (hardware-configuration.nix is autogenerated upon installation)
# paths in nix expressions are always relative the file which defines them
imports =
[
./hardware-configuration.nix
./my-dev-tools.nix
./my-desktop-env.nix
./etc.nix
];
# Name your host machine
networking.hostName = "mymachine";
# Set your time zone.
time.timeZone = "Europe/Utrecht";
# Enter keyboard layout
services.xserver.layout = "us";
services.xserver.xkbVariant = "altgr-intl";
# Define user accounts
users.users =
{
myuser =
{
home = "/home/myuser";
extraGroups = [ "wheel" "networkmanager" ];
isNormalUser = true;
uid = 1000;
};
};
# Install some packages
environment.systemPackages =
with pkgs;
[
ddate
testdisk
zsh
];
# Enable the OpenSSH daemon
services.openssh.enable = true;
}
For inspiration, a variety of NixOS configuration files made by community members can be found in the Configuration Collection.
Imperative Operations
User Environments
In addition to declarative system configuration, NixOS offers the imperative nix-env
command which can be used to install packages at the user level. Packages installed using nix-env
are only available to the given user, and do not change system state.
Searching for packages | nix-env -qaP '.*packagename.*'
|
Installing a package | nix-env -i packagename
|
List installed packages | nix-env -q
|
Uninstall packages | nix-env -e packagename
|
Upgrade packages | nix-env -u
|
Channels
Nix channels are mechanisms for distributing Nix expressions as well as the associated binaries for them; a Nix channel corresponds to a repository in a conventional package management system. Official Nix channels are automatically updated once tests are passed in Nixpkgs' Hydra instance. It is also possible to create one's own Nix channels, but here we focus the official channels. A full list of the available official channels is available.
NixOS is distributed through a number of channels. These NixOS channels can be broadly categorised into stable and unstable channels, and large and small channels:
- Stable/unstable:
- Stable channels (
nixos-17.09
) provide conservative updates for fixing bugs and security vulnerabilities, but do not receive major updates after initial release. New stable channels are released every six months. - Unstable channels (
nixos-unstable
,nixos-unstable-small
) correspond to the main development branch of Nixpkgs, delivering the latest tested updates on a rolling basis.
- Stable channels (
- Large/small:
- Large channels (
nixos-17.09
,nixos-unstable
) provide binary builds for the full breadth of Nixpkgs. - Small channels (
nixos-17.09-small
,nixos-unstable-small
) are identical to large channels, but contain fewer binaries. This means they update faster, but require more to be built from source.
- Large channels (
Most users will want the stable/large channel, currently nixos-17.09
.
Like packages installed via nix-env
, channels are managed at user-level. NixOS uses the channels set for the root
user to update the system-wide configuration; channels set for other users control only the user environment for that user. If you wish to change the channel used by the system-level configuration (/etc/nixos/configuration.nix
), ensure you run the correct nix-channel
command as root:
Listing current channels | nix-channel --list
|
Adding a primary channel | nix-channel --add https://nixos.org/channels/channel-name nixos
|
Adding other channels | nix-channel --add https://some.channel/url my-alias
|
Remove a channel | nix-channel --remove channel-alias
|
Updating a channel | nix-channel --update channel-alias
|
Updating all channels | nix-channel --update
|
Note that updating channels won't cause a rebuild in itself; if you want to update channels and rebuild, you can run nixos rebuild --upgrade
to do both in one step.
Internals
Comparsion to traditional Linux Distributions
The main difference between to Linux Distribution is that NixOS does not follow the Linux Standard Base file system structure. On LSB-compliant systems software is stored under /{,usr}/{bin,lib,share} and configuration is generally stored in /etc .
Software binaries become available for the user environment if they are placed in the bin folder of the LSB. When software is compiled with dynamic library links it will look up the required libraries in the LSB folders ( /usr/lib ) and load it.
In NixOS however this structure is not in place. Instead, user environments are essentially a number of symbolic links to all required packages and auxiliary files. These environments are stored in nix/var/nix/profiles . Each user maintains its own environment. The booted system profile is stored in a similar fashion but also contains the kernel, firmware, configuration and startup files.
Because there is no standard library folder, all packages will be compiled with explicit paths to the libraries it requires. The nix package manager will ensure that the referenced paths are available in the store. The explicit pinning of library versions makes a reproducible Operating System achievable.
All generated binaries, libraries and configuration is stored in the read-only /nix/store path.
see also: Nix vs. Linux Standard Base
Usage of the Nix Store
A lot of confusion for newcomers arises from the fact that configuration is stored in the read-only nix store along with all the installed packages. This fact makes it impossible to manually edit system configuration, all configuration changes must be performed by editing the /etc/nixos/configuration.nix file. NixOS provides the Modules System for editing all required configurations. Users should first check if an option for the configuration they require already exist before manually adding files or configuration via low-level NixOS features like activation scripts.
The system purity makes it possible to share system configuration without the need to edit multiple files. If you provide the same inputs, same version of nixpkgs and configuration.nix you will get the exact same booted system once deployed.
Modules
The NixOS module system as defined in Nixpkgs provides the means necessary to customize the configuration of the Operating System. It is used to enable and customize services such as nginx, enable firmware and customize the kernel.
All module-configuration is generally performed by adding the option entries into your configuration.nix. Most samples in the wiki are generally about the customization of the operating system and therefore require you to add the said options to you configuration file.
NixOS modules implement a typing system which allows type validation and merging of module options which are defined in multiple places. By that you could import multiple files and update options in multiple locations:
configuration.nix
{
imports = [
./basic-webserver.nix
./blog.nix
];
}
basic-webserver.nix
:
{
services.nginx.enable = true;
services.nginx.virtualHosts."example.com" = {
root = "/var/www/example.com";
};
}
blog.nix
{
services.nginx.virtualHosts."blog.example.com" = {
root = "/var/www/blog.example.com";
};
}
see also: NixOS Manual about writing Modules
Generations
Environments are versioned via generation, every change to an environment will create a new generation. With this structure it is possible to revert changes with the help of the nix package manager. This is also true for the booted system, however a restart is required for changing the kernel.
Rolling back can be done via:
$ nix-env --rollback # roll back a user environment
$ nixos-rebuild switch --rollback # roll back a system environment
See also
- NixOS Modules System, a library for modular expression definitions which powers NixOS configuration language.
- NixOS Testing library, a library for creating reproducible infrastructure tests, based on Nixpkgs, NixOS, QEMU and Perl.