Deklarativa byggen med Nix/NixOS
License: CC-BY-SA | Baserad på shwr
Published: June 4, 2015
Deklarativa byggen med Nix/NixOS
Av Edward Tjörnhammar
En kanske för advancerad introduktionIntro
- Vem är jag
- Antaganden
- Angående frågor
Översikt
- Övergripande mål & syfte
- Nix
- Språket
- Byggsystemet
- Koncepten
- Användning
- NixOS
- nixpkgs
- Systemet
- Moduler
- Exempeldeklarationer
Övergripande Mål
- Isolering mellan produkter
- m.a.p. bygg- och exekveringsmiljö
- Referentiell transparens m.a.p. bygginstruktioner
- Att vara en experimentell platform
Syfte
- Repeterbara deterministiska byggen leder till lättare igenkännbara fel
- Källkoden: ändrade signatur, är borta!?
- Kompileringsfel, dålig bygginstruktion?
- Testerna gick inte längre igenom!
- Kanske ovanstående för något, eller introducerat, av beroenderna?
- Transaktionella uppgraderingar
- Kan ersätta konfigurationshanteringsverktyg
- Närmre mellan utveckling, kontinuerlig integration, provisionering
Nix
Språket Nix
- Funktionellt formaliserat med en vänsterrekursiv grammatik
- Rent (referentiellt transparent), en funktion ger alltså alltid samma svar för samma input
- Lat evaluerat, utifrån-in istället för innifrån-ut
- Otypat, med några primitiva undantag:
- pather, spather, urlar, boolar, intar, listor, funktioner och attributset
- Inte homoikoniskt, alltså ingen LISP, se Guix/GuixSD
Fixpunktkombinatorn
Exempelnix-repl> fix = f: let x = f x; in x
Ger mig ett x där x är utvärderat på sig själv med f.
nix-repl> (fix (x: { a="Hejsan"; b="Världen"; c=x.a+" "+x.b+"!"; })).c
nix-repl> "Hejsan Världen!"
Byggsystemet Nix
- Byggs med C++, bison, flex, coreutils, perl, libxml , curl!
- Installeras under din användare med:
curl https://nixos.org/nix/install | sh
- Kan anropas över RPC
- Nix skall fungera med GNU-system, OS X och under Cygwin
Sökvägar
- Används för att namnge slutgiltiga attributset
- Refereras i språket med vinkelparenteser:
<tjonix/moduler/smartahemmet.nix> <kneget/paket/tidsredovisning.nix>
- Söks efter med $NIX_PATH:
export NIX_PATH=“tjonix=$HOME/nix/tjonix:kneget=$HOME/nix/kneget:$NIX_PATH”
- Kan överskridas individuellt med
-I
växeln:-I tjonix=https://tjornhammar.com/bygg/funkis/tjonix-0.1.2.tar.gz
Nomenklatur
- Utprodukter (outputs): grunda prefixinstallationer av ett paket
- Deriverare (derivations): listar andra beroende deriverare samt källfiler
- Slutningar (closures): aggregeringen av alla beroende utprodukt(er)
- Profiler (profiles): aggregerar en bunt slutningar
- Miljöer (environments): är profiler med miljövariabler, mjuklänkar
Utprodukter
find $(nix-build ‘<nixpkgs>’ -A nylon) -type f
/nix/store/my4xkz7v1m7amvcy2r69p9s5gab8n60b-nylon-1.21/bin/nylon
/nix/store/my4xkz7v1m7amvcy2r69p9s5gab8n60b-nylon-1.21/share/man/man1/nylon.1.gz
Utprodukter (forts.)
ldd $(nix-build ‘<nixpkgs>’ -A nylon)/bin/nylon
linux-vdso.so.1 (0x00007ffd0b2b2000)
libevent-2.0.so.5 => /nix/store/l73jvl87dbys0iv1cfwnvkikf6rya23r-libevent-2.0.22/lib/libevent-2.0.so.5 (0x00007f506cd36000)
libresolv.so.2 => /nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21/lib/libresolv.so.2 (0x00007f506cb1f000)
libnsl.so.1 => /nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21/lib/libnsl.so.1 (0x00007f506c907000)
libc.so.6 => /nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21/lib/libc.so.6 (0x00007f506c567000)
libpthread.so.0 => /nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21/lib/libpthread.so.0 (0x00007f506c34a000)
/nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21/lib/ld-linux-x86-64.so.2 (0x00007f506cf7d000)
Deriverare - Nix
oberoende.nix | build.sh |
---|---|
|
|
nix-build oberoende.nix
|
falerar! |
Deriverare - Rå
nix-instantiate oberoende.nix -> /nix/store/ngcpv5nx6q0sxj138ab02jds4wykybf0-oberoende-paket.drv
Derive([("out","/nix/store/6qcdj32sdpkpvgii08p3kf5zis29dcsm-oberoende-paket","","") ]
, []
, ["/nix/store/pnvdaqw27appm87d589v012mriggndms-build.sh"]
, "x86_64-linux"
, "/nix/store/pnvdaqw27appm87d589v012mriggndms-build.sh"
, []
, [ ("builder","/nix/store/pnvdaqw27appm87d589v012mriggndms-build.sh")
, ("finurlig","trasig")
, ("name","oberoende-paket")
, ("out","/nix/store/6qcdj32sdpkpvgii08p3kf5zis29dcsm-oberoende-paket")
, ("system","x86_64-linux")
])
Slutningar
nix-store -q –graph $(nix-build ‘<nixpkgs>’ -A nylon) | awk -F’->‘’/->/{print $1}’ | sort -u
"/nix/store/5hkwn27l77b7c37z7812acdf4p9ldr6m-linux-headers-3.12.32"
"/nix/store/5jnfr7xzg0prz618l3nayibi51jpj9ym-perl-5.20.2"
"/nix/store/60nvlmj63b87xxfw20sg7ww3g84ijcq5-zlib-1.2.8"
"/nix/store/6qh72zn2431fgdzlvzzdgnm8alvl2y02-bzip2-1.0.6"
"/nix/store/90j6b3cacg3ak0760dkda2rfi2lwp6cq-attr-2.4.47"
"/nix/store/bnlcsbw7nhd21vw4xssnxwi9y7h2asjj-coreutils-8.23"
"/nix/store/cpv8pyc772cx0spzz76sa6dvsf6555dh-gcc-4.8.4"
"/nix/store/dbxpkswwc7rh6g1iy6dwqklzw39hihb1-bash-4.3-p33"
"/nix/store/i0l0jjkk82wsqz9z5yhg35iy78bjq684-glibc-2.21"
"/nix/store/jk37x39wbkban1yzxgxik0pdlgvp0c9p-acl-2.2.52"
"/nix/store/l73jvl87dbys0iv1cfwnvkikf6rya23r-libevent-2.0.22"
"/nix/store/z6vp5aix4ks1zdjdry7v7dahg8dd02sy-python-2.7.10"
"/nix/store/zzjmzg5xpns5mcnj01ss6qsd4yj706zh-openssl-1.0.1m"
Filerna i Nix (byggen)
*.nix
: nixdeklarationer kompileras ofta direkt till 3. mednix-build
*.drv
: deriverarebeskrivningar skapas från*.nix
genomnix-instantiate
$out
: utprodukt, byggs från*.drv
mednix-store --realise
.nix ≻ .drv ≻ $out
Filerna i Nix (cache)
*.nar
: nixarkiv skapas från utprodukten mednix-store --dump
, används för cache:ar*.narinfo
: signaturfil för nixarkiven, m.a.p. en cache skapas tillsammans med nixarkiv mednix-push
$out ≻ .nar ≻ .narinfo
Typisk användning
- Installera cmake i profilen dev:
nix-env -i cmake -p dev
- Installera steam i profilen lek:
nix-env -i steam -p lek
- Ta bort cmake från dev:
nix-env -e cmake -p dev
- Aktivera lek:
nix-env --switch-profile lek
- Se historiken för dev:
nix-env --list-generations -p dev
- Återställ dev med cmake:
nix-env --switch-generation 1 -p dev
- Uppdatera pakeddefinitioner:
nix-channel --update
Typisk avlusning
- Starta ett skal med curl som beroende:
nix-shell ‘<nixpkgs>’ -p curl
- Starta ett skal för att manuellt köra byggfaserna för curl:
nix-shell ‘<nixpkgs>’ -A curl
- Inspektera miljön för curl
nix-store --print-env $(nix-instantiate ‘<nixpkgs>’ -A curl)
NixOS
nixpkgs
- Standardmiljön
stdenv{Linux, Darwin, Native}
- Bootstrap, Miljövariabler, byggfaser, pre och post faser, …
{unpack, patch, configure, build, install}Phase
- Hjälpfunktionerna
stdenv.mkDerivation
pkgs.callPackage
- Drar in ett
system
ochplatform
den är avsedd att fungera på - Adaptrar för korskompilering(
crossSystem, crossDrv
), statiska byggen - Känt system?
nix-build --argstr system armv7l-linux
- Paketdefinitioner
pkgs
Utveckla med Nix/nixpkgs
Paketdefinition, default.nix | Utgåva, release.nix |
---|---|
|
|
nix-build release.nix
|
Överskridningar (användare)
~/.nixpkgs/config.nix
{
packageOverrides = pkgs: with pkgs; {
screamd = import /home/edwtjo/repos/egna/screamd/default.nix {
inherit stdenv catch cmake;
};
};
}
Överskridningar (system)
/etc/nixos/configuration.nix
{ config, lib, pkgs, ... }: {
nixpkgs.config.packageOverrides = self: with self; {
screamd = import /home/edwtjo/repos/egna/screamd/default.nix {
inherit stdenv catch cmake;
};
xfce = xfce // {
libxfce4ui = lib.overrideDerivation (xfce.libxfce4ui) (attrs: {
postInstall = ''
sed -i -e "/Super/d" $out/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml
'';
});
};
}
Användningsflaggor
packageOverrides = self: with self: {
useUnfreeCodecs = true;
unisonX11 = unison.override{ enableX11 = true; };
mplayerUF = mplayer.override{ useUnfreeCodecs = true; };
idea8 = idea.idea-community.override{ jdk = openjdk8; };
}
NixOS
- systemdbaserat
- Logiskt strukturerat kring moduler
- Systemets baslayout följer i inte FHS/LSB
- Bor numera i nixpkgs/nixos
- Realiseras med en systemprofil och miljö
- Kan byggas med
nix-build ‘<nixpkgs/nixos>’ -A system
- För att byta till det nybyggda systemet
nixos-rebuild switch
- För att byta till det nybyggda systemet
Tjänsteexempel
{ config, lib, pkgs, ... }: {
systemd.services.screamd = {
description = "MCast to DSP Screamer";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.screamd}/bin/screamd";
};
}
Moduler
{ config, lib, pkgs, ... }: with lib; {
options.tjonix.mosh.enable = mkEnableOption "Enable mosh usage on this node";
config = mkIf config.tjonix.mosh.enable {
environment.systemPackages = with pkgs; [ mosh ];
networking.firewall.allowedUDPPortRanges = [{ from = 60000; to = 61000; }];
};
}
Exempel
Snabbt, långsamt eller skippa?SSH rootåtkomst
/etc/nixos/ssh-rootaccess.nix
{ config, pkgs, ...}: {
services.openssh.enable = true;
users.extraUsers.root.openssh.authorizedKeys.keyFiles = [ ./id_edwtjo.pub ];
}
HTPC = Kodi + Genesis + SVTPlay
{ config, pkgs, ... }: {
imports = [ ./ssh-rootaccess.nix ];
services.xserver.enable = true;
services.xserver.autorun = true;
services.xserver.displayManager.slim.enable = true;
services.xserver.displayManager.slim.defaultUser = "htpc";
services.xserver.displayManager.slim.autoLogin = true;
services.xserver.desktopManager.kodi.enable = true;
nixpkgs.config.kodi.enableSVTPlay = true;
nixpkgs.config.kodi.enableGenesis = true;
users.extraUsers.htpc = { uid = 1001; createHome = true; group = "htpc";
home = "/home/htpc"; shell = pkgs.zsh + "/bin/zsh"; };
users.extraGroups.htpc.gid = 1001;
}
NixOS Gamestation
{ config, pkgs, ... }: {
imports = [ ./htpc.nix ];
nixpkgs.config.kodi.enableAdvancedLauncher = true;
nixpkgs.config.retroarch = {
enable4do = true; enableBsnesMercury = true; enableDesmume = true;
enableFBA = true; enableFceumm = true; enableGambatte = true;
enableGenesisPlusGX = true; enableMupen64Plus = true; enableNestopia = true;
enablePicodrive = true; enablePrboom = true; enablePPSSPP = true;
enableQuickNES = true; enableScummVM = true; enableSnes9x = true;
enableSnes9xNext = true; enableStella = true; enableVbaM = true;
enableVbaNext = true;
};
environment.systemPackages = with pkgs; [ kodi-retroarch-advanced-launchers ];
}
Användarens egen Zotero miljö
{
packageOverrides = self: with self; rec {
zoteroEnv = let
platform = "Linux-x86_64";
drv = buildEnv {
name = "zotero-xpdf";
paths = [ zotero xpdf sqlite ];
postBuild = ''
makeWrapper "${xpdf}/bin/pdftotext" "$out/bin/pdftotext-${platform}"
makeWrapper "${xpdf}/bin/pdfinfo" "$out/bin/pdfinfo-${platform}"
'';
};
in lib.overrideDerivation drv (x : {buildInputs = x.buildInputs ++ [ makeWrapper ];});
};
}
Ändra scheduler till deadline
{ config, pkgs, ... }: {
nixpkgs.config.packageOverrides = self: with self; {
stdenv = stdenv // {
platform = stdenv.platform // {
kernelExtraConfig = ''
IOSCHED_DEADLINE y
DEFAULT_DEADLINE y
DEFAULT_IOSCHED "deadline"
'' ;
};
};
};
}
NixOS + ck-sources
{ config, pkgs, ... }: {
boot.kernelPackages = pkgs.linuxPackages_ck_4_0;
nixpkgs.config.packageOverrides = self: with self;
let
ck-sources = (import <nixpkgs/pkgs/os-specific/linux/kernel/generic.nix> {
inherit perl buildLinux; inherit (linux_4_0) src;
version = linux_4_0.version + "-ck1";
stdenv = stdenv // { platform = stdenv.platform // {
name = "ricer";
};};
extraConfig = ''
SCHED_BFS y
'';
kernelPatches = [ ({ patch = fetchurl {
url = "http://ck.kolivas.org/patches/4.0/4.0/4.0-ck1/patch-4.0-ck1.bz2";
sha256 = "1lkckz8j5dapmdq7nkaxp541hvflw1ky9gvnsk5s0a440hns6g5y";
};}) ];
});
in { linuxPackages_ck_4_0 = recurseIntoAttrs (linuxPackagesFor ck-sources linuxPackages_4_0); };
}
Vad nu?
Matnyttigt för den som vill veta merIntressanta nixrepon
- MichaelRaskin:s initlösa konfigurationer
- @zalora:s defnix/defnixos
- @openlab-aux:s vuizvui
- @wkennington:s konfigurationer
Gott å blandat
- Nix Loves Haskell: slajds video
- nixos-containers for web development
- Nix-NixOS-NixOps: From Development to Deployment
- nix-exec kör program direkt från nixuttryck
- Nix IDEA plugin: nixitch (av mig)
- Inlägg om statiska omfång och att överskrida attribut
Att ta med
- Förståelse för varför utprodukter blir isolerade med Nix
- Vilka olika steg som inbegrips
- Att det finns en hel del hjälp att få i nixpkgs
- Förstå att NixOS bara är en drös moduler
- Kanske förstå hur man bygger en nixos konfiguration