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