An overview of
the Nix ecosystem

LilleFP14
2019-04-25

by Julien Dehos

The Nix project

History

Motivation

  • purely functional packaging system
  • reproducible/isolated/composable packages
  • reliable upgrades
  • declarative configuration model

Functional packaging

Implementation

  • no Filesystem Hierarchy Standard (FHS)
  • /nix/store/
  • hash codes
  • symbolic links + profiles/environments

Dependency graph

Derivation

examples/hello.nix:

Build a derivation

$ nix-build hello.nix

these derivations will be built:
  /nix/store/iclkh6vn27jga8xvwpyv3qx1crjcrw8i-hello-2.10.drv
...
/nix/store/kl7sr2m0cds7ag8b23g2i58cn2b0xyqj-hello-2.10

+ a symbolic link ./result

Result

$ tree ./result

    result
    ├── bin
    │   └── hello
    ...

$ ./result/bin/hello

    Bonjour, le monde !

The Nix ecosystem

  • Nix: language
  • Nix: tools (nix-env, nix-build, nix-shell…)
  • Nixpkgs: package collection
  • NixOS: linux distribution
  • Nixops: deployment tool
  • Hydra, disnix…

The Nix language

Computer configuration

Nix can configure a system

  • configs, packages, services
  • declarative configuration model
  • NixOS
  • Nix on Linux/macOS

Installing Nix on Linux/macOS

sh <(curl https://nixos.org/nix/install) --daemon

Nix manual, Chapter 4

Installing NixOS

cfdisk /dev/sda  # ...
mkfs.ext4 /dev/sda1
mount /dev/sda1 /mnt
nixos-generate-config --root /mnt
vi /mnt/etc/nixos/configuration.nix  # ...
nixos-install

NixOS manual, Chapter 2

System configuration

  • NixOS
  • superuser
  • /etc/nixos/configuration.nix

update the system:

# nixos-rebuild switch

+ rollback, generations…

User configuration

  • NixOS or Nix
  • user
  • imperative management: nix-env -i/-e
  • or “packageOverrides”
  • or “overlays”: fixed-point layer composition
  • or “home manager”: declarative configuration

User configuration with packageOverrides

~/.config/nixpkgs/config.nix:

install/update:

$ nix-env -iA nixos.myPackages

Configuring Vim with Nix

~/.config/nixpkgs/vim.nix:

~/.config/nixpkgs/config.nix:

list available vim plugins:

$ nix-env -qaP -A nixos.vimPlugins

vimPlugins.pluginnames2nix    vim-plugin-names-to-nix
vimPlugins.a-vim              vimplugin-a-vim-2010-11-06
vimPlugins.ack-vim            vimplugin-ack-vim-2018-02-28
vimPlugins.acp                vimplugin-acp-2013-02-05
vimPlugins.agda-vim           vimplugin-agda-vim-2018-05-23
vimPlugins.ale                vimplugin-ale-2018-07-25
...

Software packaging

Nix can package software

  • in C/C++, Python, Haskell…
  • by writing Nix derivations (default.nix)
  • and using Nixpkgs

Example: C++/cmake project

showimg/CMakeLists.txt:

dependencies: opencv, pkg-config, cmake

Example: classic workflow

sudo apt-get install cmake pkg-config libopencv-dev
mkdir build
cd build
cmake ..
make
sudo make install

Example: Nix packaging

build derivation:

$ nix-build

    these derivations will be built:
      /nix/store/axzyh26z6k60yi7nsz71i4fk6734lgdl-showimg.drv
    ...
    /nix/store/2lpqmmyvaz83awzpxxzwqansj8rhkz0v-showimg

$ ./result/bin/showimg bob.png 

Nix knows how to build a cmake project !

install/remove derivation:

$ nix-env -i -f .

$ showimg bob.png 

$ nix-env -e showimg

run environment:

$ nix-shell 

[nix-shell]$ mkdir mybuild

[nix-shell]$ cd mybuild/

[nix-shell]$ cmake ..

Example: Nix packaging (2)

Nix can override many options:

see the opencv derivation

$ nix-shell
...

[nix-shell] $ gcc --version
gcc (GCC) 6.4.0

Development environment

Nix environments

  • useful for setting up a project
  • ad-hoc environments, shell.nix, default.nix
  • Nixpkgs manual

Example 1: GNU hello

ad-hoc environment:

$ nix-shell -p hello

[nix-shell]$ hello
Bonjour, le monde !

[nix-shell]$ exit
$ nix-shell -p hello --run hello
Bonjour, le monde !

examples/hello/shell.nix:

$ nix-shell --run hello
Bonjour, le monde !

Example 2: Python packages

python virtual environment:

$ virtualenv -p python3 myenv
...

$ source myenv/bin/activate

(myenv) $ pip install numpy
...

(myenv) $ python
Python 3.6.8 
>>> import numpy
>>> 

Nix ad-hoc environment:

$ nix-shell -p 'python3.withPackages(ps: [ps.numpy])'

[nix-shell]$ python
Python 3.6.8  
>>> import numpy
>>> 

examples/numpy/shell.nix:

$ nix-shell --run python
Python 3.6.8  
>>> import numpy
>>> 

Example 3: composing environments

$ nix-shell --run python
Python 3.6.8
>>> import os
>>> os.system('showimg bob.png')

Haskell

Haskell infrastructure in Nix

List Haskell packages/compilers

$ nix-env -qaP -A nixos.haskellPackages
nixos.haskellPackages.a50                 a50-0.5
nixos.haskellPackages.AAI                 AAI-0.2.0.1
nixos.haskellPackages.abacate             abacate-0.0.0.0
...
$ nix-env -qaP -A nixos.haskell.compiler
nixos.haskell.compiler.ghc7103            ghc-7.10.3
nixos.haskell.compiler.ghc802             ghc-8.0.2
nixos.haskell.compiler.ghc822             ghc-8.2.2
...

Ad-hoc environments

$ nix-shell --run ghci -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.random])"

GHCi, version 8.4.4: http://www.haskell.org/ghc/  :? for help
Prelude> import System.Random 
Prelude System.Random> :set -XScopedTypeVariables 
Prelude System.Random> x::Double <- randomIO 
Prelude System.Random> x
0.114730187676368

Script files

$ ./myrandom.hs 
0.9742300417428591

Cabal (example 1)

myrandom/myrandom.cabal:

name:                myrandom
version:             0.1
build-type:          Simple
cabal-version:       >=1.10
license:             MIT

executable myrandom
  main-is:             myrandom.hs
  default-language:    Haskell2010
  build-depends:       base, random

myrandom/default.nix:

run environment:

$ nix-shell 
...

[nix-shell]$ cabal run
...
Running myrandom...
0.29070504359756477

build derivation:

$ nix-build 
...

$ ./result/bin/myrandom 
0.6441685176316507

install derivation:

$ nix-env -i -f .

$ myrandom 
0.9953143854386685

Cabal (example 2)

myrandom/default2.nix:

$ nix-shell default2.nix

[nix-shell]$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.2.2

Stack

stack.yaml:

$ stack --nix build --exec myrandom
...
0.8784417204074236

Stack, Nix integration

Continuous Integration

Nix for CI

Quick & dirty gitlab-ci

myrandom/.gitlab-ci.yml:

Hydra: installation on NixOS

/etc/nixos/configuration.nix:

# su - hydra

[hydra@nixos:~]$ hydra-create-user toto --password toto --role admin
creating new user `toto'

Hydra: CI pipeline

myrandom/release1.nix:

Hydra: other jobs

  • multiple systems/platforms
  • source/binary tarballs
  • test coverage

Deployment

Nix deployment tools

  • dockerTools: docker images
  • nixops: NixOS machines
  • nixos-container, cachix, kubenix…

Docker images

myrandom/myrandom-docker.nix:

$ nix-build myrandom-docker.nix 
building '/nix/store/0rmrz4fvhdh6vjyrbqnwfrxgnfp4x9sw-cabal2nix-myrandom.drv'...
...

$ docker load < result 
1114fa18ba6b: Loading layer [========>]  10.24kB/10.24kB
...

Nixops

  • Nixops can deploy NixOS machines
  • AWS, GCE, Azure, VirtualBox…
  • declarative configuration model
  • Nixops manual

Nixops: example

myusers:

  • PostgreSQL database
  • HTTP server (Haskell)
  • VirtualBox VM

files:

  • default.nix
  • myusers.cabal
  • myusers.hs
  • myusers.sql
  • myusers-nixops.nix

myusers-nixops.nix:

deployment:

$ nixops create -d vm1 myusers-nixops.nix
...

$ nixops deploy -d vm1 --force-reboot
...

$ nixops ssh -d vm1 webserver

[root@webserver:~]# systemctl status myusers.service 
● myusers.service
...

Conclusion

Nix ecosystem

  • functional packaging system, functional language
  • configs, packages, environments, CI, deployment…
  • reproducible, isolated, composable…
  • very promising approach

But

  • very different approach
  • learning curve
  • needs a lot of disk space

References

Thank you !

Questions & comments ?