Tag: nix

Short introduction to Nix, NixOS and NixOps

NixOps: Declarative Provisioning and Deployment

  • It is declarative. There is no difference between doing a new deployment or doing an
    upgrade of an existing deployment. The resulting machine configurations will be the
    same, allowing deployments to be upgraded or reproduced reliably.

  • There are several prominent configuration management systems with declarative models,
    such as Cfengine, Puppet and Chef. However, the systems they manage still have
    underlying imperative configuration models, such as configuration files in /etc
    that are updated in place by deployment actions. Thus the result of a deployment may
    still depend on the previous configuration of the system.

  • It performs provisioning. For instance, if we instantiate an Amazon EC2 machine
    as part of a larger deployment, it may be necessary to put the IP address or host
    name of that machine in a configuration file on another machine, and to ensure that
    any changes are propagated properly.

  • It allows abstracting over the target environment. The same specification can be
    deployed to different cloud backends.

  • NixOps ensures that machines can talk to each other, e.g. by creating tunnels
    between machines in different EC2 regions.

  • With NixOps, the same toolchain supports both development and production use.
    By contrast, Vagrant provisions VirtualBox virtual machines to set up test
    environments which can then be configured by tools such as Chef. To deploy to e.g.
    EC2, other tools are required.

  • It uses a single configuration formalism (Nix’s purely functional language) for
    package management and system configuration management. This makes it very easy to add
    ad hoc packages to a deployment.

  • The functional approach is less suited to automatically finding optimal solutions
    to sets of constraints (e.g. to find a deployment that satisfies a feature model).

  • NixOps tracks the state of deployments in a SQLite database.

Ref: Charon: Declarative Provisioning and Deployment

NixOS

NixOps deploys NixOS machines, so we start with a brief overview of NixOS' configuration
model. In NixOS, machines are configured by providing a file (typically
/etc/nixos/configuration.nix) that specifies the desired configuration of the system.
For instance, the following file specifies that we want a machine that runs the
Apache web server:

    { services.httpd.enable = true;
      services.httpd.documentRoot = "/data";
    }

Configuration changes are realised by running the command nixos-rebuild, which
evaluates the system configuration, builds all dependencies, and finally starts,
restarts or stops any new, changed or removed system services in the new configuration.

For instance, if the previous configuration had services.httpd.enable = false, then
running nixos-rebuild will cause Apache httpd to be built or downloaded (if it wasn’t
already present in the system), an httpd.conf configuration file to be generated, and
finally httpd to be started.

In NixOS, all system services are started and monitored using the systemd program
(ref: https://nixos.org/nixos/manual/index.html#sec-systemctl). You can ask for detailed
status information about a unit, for instance, the PostgreSQL database service:

$ systemctl status postgresql.service

More resources:

Nix

NixOS builds on Nix, a purely functional package manager. NixOS uses Nix to build
packages and other static system configuration artifacts such as configuration files in
a reproducible way. The file configuration.nix is essentially a parameter to a Nix
function that evaluates to a large dependency graph of packages, configuration files and
boot scripts in the Nix store, together constituting the system.

Nix stores these artifacts in the filesystem in locations such as
/nix/store/wjbcr40b...-apache-httpd-2.2.23/, where wjbcr40b... is a cryptographic
hash of the dependencies of the artifact.
As a result when upgrading the old system configuration is never overwritten, allowing
efficient rollbacks and nearly atomic upgrades. This is super helpful when we
accidentally crash our system.

Here is a nice tour of Nix where you can get more
familiar with Nix.

More resources:

[NixCon 2019] Reading Nix expressions (notes)

This are my notes from the Reading Nix expressions talk in NixCon 2019.

Nix package language has a similar syntax to the "JSON meets functional language concepts". E.g. you have Let-expressions which I would say is a functional concept (ref: https://en.wikipedia.org/wiki/Let_expression) - I first saw it in Elm and Haskell.

An important thing to keep in mind is that Nix is a lazy language so some code might not get evaluated if it is not called. This means you can actually read the code from the "middle". For example, you can start reading this config https://github.com/jwiegley/nix-config/blob/master/default.nix in line 12 and then continue to the next one. Once you see a variable like e.g. ${version} you can "evaluate" it in your head (in this case version is defined in line 1).

The point is that some variables/functions can be defined but might not get called so Nix won't evaluate them. This is completely different from how e.g. Python works.

Functions

Nix functions are just lambda expressions. Example:

a: b: a + b

Another representation is keyword arguments or a set pattern:

{ a, b }: a + b

This one is the most popular. You can call this function with a and b attributes. If you need additional arguments you can use an ellipsis (...):

{ a, b, c, ... }: a + b + c

This will work on any set that contains at least the three named attributes.

Ref: https://nixos.org/nix/manual/#ss-functions

Buildins

Nix expression evaluator has a bunch of functions and constants built in. For example:

  • toString e (Convert the expression e to a string)
  • import path (Load, parse and return the Nix expression in the file path)
  • throw s (Throw an error message s. This usually aborts Nix expression evaluation)
  • map f list (Apply the function f to each element in the list list)

There are tons of other [buildins available][https://nixos.org/nix/manual/#ssec-builtins].

Keywords

We have several reserved keywords in Nix:

Operators

Nix also provides a bunch of operators like Arithmetic addition, subtraction, division, etc.

See this link for the full list of operators.


This is the very basic of the Nix language. You will need the above knowledge if you will want to start hacking nix config files. Or should I say if you want to know what you are actually doing while hacking nix config files 🙂

Navigation