rethinking

NUUG Oct 2015

package management

#nixos

Rok Garbas, @garbas

Ever heard somebody complaining about packaging?

Lets meet the family...

Nix

Nixpkgs

Hydra

NixOS

NixOps

Why Nix?

Features or

Nix protects me against me.
Nix exposes the things I forget.
Nix let's me do things multiple times consistently, even on different machines.
Nix, the one language to rule them all.

Quotes by Rob Vermas - http://nixer.ghost.io/why/

Is this all that Nix can do?

Hydra

NixOS

NixOps

source / binary model

multi-user

reproducable

multi-version

portable

Installing Nix

TO INSTALL

  % curl https://nixos.org/nix/install | sh


TO UNINSTALL

  % rm -Rf /nix
  % rm -Rf ~/.nix*

Friends sometimes let friends curl to shell

Nix protects me, against me

UPDATE CHANNELS (look at this as apt-get update)

  % nix-channel --update


INSTALL "tig" application

  % nix-env --list-generations
  1002   2015-01-23 04:29:40   
  1003   2015-01-23 04:44:51

  % nix-env -i tig

  % nix-env --list-generations
  1002   2015-01-23 04:29:40   
  1003   2015-01-23 04:44:51   
  1004   2015-01-23 04:50:11

UNDO / ROLLBACK

  % nix-env --rollback   <or  nix-env --switch-generation 1003>

  % nix-env --list-generations
  1002   2015-01-23 04:29:40   
  1003   2015-01-23 04:44:51   

Example Nix expression 

{ stdenv, fetchurl, ncurses, asciidoc, xmlto
, docbook_xsl, docbook_xml_dtd_45, readline
, makeWrapper, git
}:

stdenv.mkDerivation rec {
  name = "tig-2.1.1";

  src = fetchurl {
    url = "http://jonas.nitro.dk/tig/releases/${name}.tar.gz";
    sha256 = "0bw5wivswwh7vx897q8xc2cqgkqhdzk8gh6fnav2kf34sngigiah";
  };

  buildInputs = [ ncurses asciidoc xmlto docbook_xsl
    readline git makeWrapper ];

  preConfigure = ''
    export XML_CATALOG_FILES='${docbook_xsl}/xml/xsl/docbook/catalog.xml ${docbook_xml_dtd_45}/xml/dtd/docbook/catalog.xml'
  '';

  enableParallelBuilding = true;
  
  ...

  ...

  installPhase = ''
    make install
    make install-doc
    mkdir -p $out/etc/bash_completion.d/
    cp contrib/tig-completion.bash $out/etc/bash_completion.d/
    wrapProgram $out/bin/tig \
      --prefix PATH ':' "${git}/bin"
  '';

  meta = with stdenv.lib; {
    homepage = "http://jonas.nitro.dk/tig/";
    description = "Text-mode interface for git";
    maintainers = with maintainers; [ garbas bjornfor iElectric qknight ];
    license = licenses.gpl2;
    platforms = platforms.unix;
  };

}

How can Nix do this?

HOOKS INTO BASH

  % echo $PATH
  /home/rok/.nix-profile/bin:/home/rok/.nix-profile/sbin:...

  % tree -L 2 `realpath ~/.nix-profile`
  /nix/store/xj8592ssnmcsn1kvbf87nm1acllwcqan-user-environment
  ├── bin
  │   ├── tig -> /nix/store/j3scw814k79mj3mm6x6yj9svvcq1plx4-tig-2.0.3/bin/tig
  │   ├── tree -> /nix/store/g75lq2kmfwx5sdqni6khv04kdklh3kq9-tree-1.7.0/bin/tree
  ├── etc
  │   ├── bash_completion.d -> /nix/store/j3scw814k79mj3mm6x6yj9svvcq1plx4-tig-2.0.3/etc/bash_completion.d
  │   └── tigrc -> /nix/store/j3scw814k79mj3mm6x6yj9svvcq1plx4-tig-2.0.3/etc/tigrc
  └── manifest.nix -> /nix/store/gjia0lic4v117fm3la3c4wkk6ig2iw3q-env-manifest.nix

/nix/store/j3scw814k79mj3mm6x6yj9svvcq1plx4-tig-2.0.3

/nix/store/

+

<hash>

+

<name>

+

<version>

Why are current tools not good enough?

Packaging instructions and metadata

Filesystem /usr

building

package

Filesystem /usr

with package in it

Stateless way of building packages

Packaging instructions and metadata

building

package A

Filesystem /nix/store/$hash-$name-$version

Packaging instructions and metadata

building

package B

Filesystem /nix/store/$hash-$name-$version

NixOS

{ pkgs, ... }:
{
  boot.initrd.luks.devices = [
    { name = "luksroot";
      device = "/dev/sda2";
      allowDiscards = true; }
  ];
  boot.kernelPackages = pkgs.linuxPackages_latest;
  boot.blacklistedKernelModules = [ "snd_pcsp" "pcspkr" ]
  boot.extraModprobeConfig = ''
    options thinkpad_acpi fan_control=1
  '';

  loader.grub.enable = true;
  loader.grub.version = 2;
  loader.grub.device = "/dev/sda";

  fileSystems = [
    { mountPoint = "/"; label = "root"; }
    { mountPoint = "/boot"; label = "boot"; }
    { mountPoint = "/tmp";
      device = "tmpfs"; fsType = "tmpfs";
      options = "nosuid,nodev,relatime";
    }
  ];

  ...
  ...

  environment.systemPackages = with pkgs; {
    gitFull
    gitAndTools.tig
    gitAndTools.gitflow
    neovim
    keybase
    ...
  };

  networking.networkmanager.enable = true;
  networking.firewall.enable = true;
  networking.firewall.allowedTCPPorts = [ 80 8080 8000 24800 ];

  users.mutableUsers = false;
  users.extraUsers."rok" =
    { createUser = true;
      extraGroups = [ "wheel" "vboxusers" "networkmanager" ] ;
      group = "users";
      home = "/home/rok";
      description = "Rok Garbas";
      shell = "/run/current-system/sw/bin/zsh";
      uid = 1000;
    };
  
  ...
  ...

  services.openssh.enable = true;

  services.printing.enable = true;

  services.enable = true;
  services.thinkfan.sensor = "/sys/class/hwmon/hwmon0/temp1_input";

  services.xserver.enable = true;
  services.xserver.autorun = true;
  services.xserver.layout = "us";
  services.xserver.windowManager.default = "i3";
  services.xserver.windowManager.i3.enable = true;
  services.xserver.windowManager.i3.configFile = pkgs.writeText "i3-config" "<this is i3_config>";
  services.xserver.desktopManager.enable = true
  services.xserver.desktopManager.xterm.enable = false;
  services.xserver.displayManager.sessionCommands = 
    xrdb -merge ${pkgs.writeText "Xresources" ("<my custom Xresources>")}
  '';

  time.timeZone = "Europe/Berlin";

  ...
  ...

  systemd.services."weechat" = with pkgs; {
    enable = true;
    description = "Weechat IRC Client (in tmux)";
    environment = { TERM = "${rxvt_unicode.terminfo}"; };
    path = [ tmux weechat rxvt_unicode.terminfo ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = "yes";
      ExecStart = "${tmux}/bin/tmux -S /run/tmux-weechat new-session -d -s weechat -n 'weechat' '${weechat}/bin/weechat-curses -d /root/dotfiles/pkgs/weechat'";
      ExecStop = "${tmux}/bin/tmux -S /run/tmux-weechat kill-session -t weechat";
    };
  };

}

NixOps

{
  network.description = "Web + Database";
  front =
    { config, pkgs, lib, ... }:
    { services.nginx.enable = true;
      services.nginx.httpConfig = "<nginx config here>";
    };
  db =
    { config, pkgs, lib, ... }:
      services.mysql.enable = true;
    };
}
{
  front =
    { config, pkgs, ... }:
    { deployment.targetEnv = "virtualbox";
    };
  db =
    { config, pkgs, ... }:
    { deployment.targetEnv = "virtualbox";
    };
}
{
  front =
    { config, pkgs, lib, ... }:
    { deployment.targetEnv = "none";
      deployment.targetHost = "xx.xx.xx.xx";
      ...
    };
  db =
    { config, pkgs, lib, ... }:
    { deployment.targetEnv = "none";
      deployment.targetHost = "yy.yy.yy.yy";
      ...
    };
}


% nix-env -i nixops

% nixops create -d deploy-vbox logical.nix vbox.nix
% nixops deploy -d deploy-vbox

% nixops create -d deploy-hw logical.nix hw.nix
% nixops deploy -d deploy-hw

It was never easier to contribute

to linux distribution


GET LATEST nixpkgs

  % git clone git://github.com/NixOS/nixpkgs.git


FIND A BUG AND FIX IT

  % cd nixpkgs
  % vim ...
  % git commit -m "tig: package updated to 1.2.3"

TEST YOUR CHANGES

  % nix-build -A tig

SEND A PULL REQUEST

Thank you

and stay "pure"

NixOS conference

14. - 15. November 2015

Berlin

http://conf.nixos.org

final words...

Rok Garbas, @garbas

rethinking package management

By Rok Garbas

rethinking package management

Packaging is a hard problem, no doubt. Still every language/distribution tries to invent packaging on their own. This leaves us (developers / sysadmins) with a big number of tools that we need to master in order to do our job. We will look at how Nix[1] and NixOS[2] can be used in todays software development processes and which are the benefits and drawbacks you might face. [1] Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible. It provides atomic upgrades and rollbacks, side-by-side installation of multiple versions of a package, multi-user package management and easy setup of build environments. [2] NixOS is a Linux distribution built on top of the Nix package manager, it is completely declarative, makes upgrading systems reliable, and has many other advantages.

  • 2,176