NixOS and the case for declarative configuration

All at Once

© Lead Image © Sergey Lavrentev,

© Lead Image © Sergey Lavrentev,

Article from Issue 163/2014

The innovative NixOS makes it easy to test and deploy new configurations – on the hardware and in the cloud

Linux distribution updates always come with a certain risk. Will all the configured services still work after the upgrade? Or, has a daemon once again changed the format of its configuration files so that the program fails to launch? Most Linux distributions are at least smart enough to avoid overwriting user-modified config files, but a defined upgrade path, which ensures the operation of the upgraded system, usually is not available.

The Nix project [1] takes an alternative approach. A Nix system is fundamentally different from normal Linux distributions. The system state is set declaratively, instead of imperatively. In other words, the complete system is defined all at once, rather than configured through a series of independent steps that each change the system state.

Nix consists of a special package manager, a package collection, a Linux distribution, and some other specialized tools. The instructions of the Nix package manager obey functional principles: an input state is entered in the function (the package manager), and the output is a new system state. Side effects are not allowed.

The Full Monty

Configuration changes in NixOS are atomic and transactional; they are performed correctly or not at all. And you can roll back to a previous system state. You can even test a new configuration on the current system without making it the default configuration for the next boot. When a transaction completes successfully, Nix updates a number of references in the last step; more specifically, symbolic links give the user a completely new environment. The old system state is still present on the computer, only the references have been updated through the symbolic links.

Nix always builds packages from the source code to adapt them for the system. Since the build process takes a lot of time, the Nix package manager automatically loads binary packages from the NixOS site, if they exist. NixOS offers the ability to install packages in a separate area as a non-root user. Also, multiple versions of a program or library can exist simultaneously on the system.

Many Platforms

You can use the Nix package manager on other Linux distributions, as well as on FreeBSD and OS X. However, the packages installed using Nix on these systems form a kind of parallel universe maintained in /nix/store. When this issue went to press, binary downloads of the current Nix version 1.6.1 were available for Debian 7.2, Ubuntu 13.10, Fedora 19, FreeBSD, and OS X, to name only the most current versions. Generic binary packages for Linux, as well as the source code, are available on the website.

Package Manager for Users

Nix's special architecture allows you to create custom software installations for each user. For most applications, a classical configuration, in which only root can add and remove software, is easier to configure and probably also more sensible. The first thing the administrator needs to do, after installing the package manager, is load the supplied shell file, which is available for binary packages in /etc/profile.d (Figure 1). If you want to build Nix yourself, be sure to use the right prefix or search in /usr/local/etc. When first called, the script generates a profile script:

Figure 1: The Nix resource script ensures that programs installed by Nix can actually be found.
# . /etc/profile.d/
creating /root/.nix-profile

To execute this script automatically, you will want to add /etc/profile.d/nix to one of the login scripts, such as $HOME/.bash_profile. Among other things, the script extends the PATH, adding the directory with executable files, /root/.nix-profile/bin. The channel (the distribution channel for software packages) is pre-configured by the script, as you can see from the /root/.nix-channels file. All that remains is to update the channel by running nix-channel --update. The following command then displays all the available packages:

nix-env -qa '*'

To see how Nix works, try installing the Vim editor with nix-env -i vim as a first test.

In addition to Vim, Nix installs the seven packages on which the Vim package depends. Because binaries already exist for all these packages, the installation only takes about a minute. In the end, you get an impression of how Nix works when it outputs the following messages:

building path(s) `/nix/store/ \
  sk8hv9y1aym6nmvpbz3nlj6r91j7 pxqq-user-environment'
created 2 symlinks in user environment

The current "User Environment" is the first path, which includes the typical hashes that Nix uses for managing its components: base-32 representations of 160-bit hashes. This user environment, which ultimately provides the user with specific program versions, consists of symlinks that reference other symlinks, which then finally point to the real packages.

This process is a bit complicated, but fortunately, you don't usually have to worry about these details, either as an administrator or a user. The binary of the newly installed Vim editor is located in $HOME/.nix-profile/bin/vim. The files and directories in $HOME/.nix-profile are updated by Nix.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More