Nix en pratique

Pierre Gambarotto

Created: 2023-03-28 mar. 08:28

Intro

  • utilisateur de nix depuis environ 4 ans
  • retour d’expérience
  • sur des cas concrets
  • ordonné par niveau de difficulté

Back to basics : nix ?

  • 20 ans !
  • nixpkgs : gestionnaire de paquetages logiciels, plus de 80000 paquets
  • cli nix : gère uniquement /nix/store et nix-daemon => possible d’installer en plus de n’importe quel OS linux/mac os/WSL

    curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | \
        sh -s -- install
    exec $SHELL # ou ouvrir un nouveau terminal
    nix --version
    
    

Plus de détails sur zero-to-nix

Si ça ne plaît pas

# sepuku
/nix/nix-installer uninstall

nix : un langage

Schématiquement :

évaluer un programme nix : on arrive à une liste de derivations à construire

construire une dérivation : créer le paquetage dans /nix/store

Basiquement simple,

Mais :

  • compliqué à maîtriser
  • minimaliste => nombreuses abstractions

    But de la présentation :

  • montrer par des exemples concrets l’intérêt de la chose

Installer un paquetage

https://search.nixos.org pour chiner parmi plus de 80000 paquets

nix profile install nixpkgs#devenv
# demande à nix-daemon :
# installe si besoin dans /nix/store/${SHA1}-devenv
# modifie mon profil utilisateur pour gérer les liens

Gestion de l’environnement utilisateur par profil

  • ajout de ~/.nix-profile/bin au PATH
  • ~/.nix-profile -> /nix/var/nix/profiles/per-user/gamba/profile
  • ~/.nix-profile/bin/devenv -> /nix/store/j5v7sh1ii9vv1bw9ngzdh5h76hh0zljh-devenv/bin/devenv

Profil = collection de liens

Chaque utilisateur est indépendant :

nix profile list
nix profile install nixpkgs#something_from_https://search.nixos.org
nix profile remove 5 # number from 'nix profile list'

L’utilisateur indique quels sont les éléments voulus dans son profil.

nix-daemon va bâtir pour chaque utilisateur une dérivation contenant les liens

Demo

ANF mathrice, novembre 2022 : openshift, openstackclient, terraform, kubectl !

❯ nix profile install nixpkgs#openshift
❯ nix profile list

❯ which oc
/home/gamba/.nix-profile/bin/oc

❯ nix profile remove 6
removing 'flake:nixpkgs#legacyPackages.x86_64-linux.openshift'

❯ which oc
which: no oc in (/home/gamba/.nix-profile/bin:/home/gamba/.nix-profile/bin:/home/gamba/.nix-profile/bin:/home/gamba/.nix-profile/bin:/home/gamba/.nix-profile/bin:/run/wrappers/bin:/etc/profiles/per-user/gamba/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin)

Notion d’environnement logiciel

Accéder à un logiciel sans forcément l’installer

nix run nixpkgs#mattermost-desktop # one shot run

nix shell nixpkgs#texlive.combined.scheme-basic
# https://nixos.wiki/wiki/TexLive
# nouveau shell !
# avec les nouveaux outils !
cat > minimal.tex <<'EOF'
\documentclass{article}
\begin{document}
Hello, Nix.
\end{document}
EOF
pdflatex minimal.tex

Devenv : péreniser un environnement logiciel

https://devenv.sh/ : surcouche à nix

  • décrire un environnement dans devenv.nix
  • l’appliquer quand on rentre dans le répertoire du projet grâce à direnv

    nix profile install nixpkgs#cachix
    cachix use devenv # cache binaire, évite de compiler
    nix profile install --accept-flake-config github:cachix/devenv/latest
    
  • partager par un dépot git

Démo sur le projet de doc de la PLM

{ pkgs, ... }:

{
  # https://devenv.sh/basics/
  env.GREET = "PLMTeam documenation";

  # https://devenv.sh/packages/
  packages = [ pkgs.git pkgs.zola ];


  languages.lua = {
    enable = true;
    package = pkgs.lua.withPackages (ps: with ps; [
      lualdap
    ]);
  };
}
  enterShell = ''
    echo $GREET
    zola --version
    git --version
    if git submodule status | grep '^-'; then
      echo "Mettez à jour les modules git avec «update-theme»"
    fi
  '';


  processes.zola-serve.exec = "zola serve";

  scripts.regen-correspondants.exec = ''
    printf "LDAP password: "
    read -s LDAPPW
    export LDAPPW
    lua ''${DEVENV_ROOT}/scripts/correspondants.lua
    unset LDAPPW
  '';


}

Autre exemple : python et tensorflow

Partager un environnement de calcul

plmlab:imt/calcul/tensorflow

tensorflowWithCuda n’est pas dans le cache binaire par défaut de nix.

instructions données aux utilisateurs pour :

  • rajouter une librairie python
  • rajouter une dépendance autre que python
{ pkgs, inputs, ... }:

{
  # https://devenv.sh/packages/
  packages = with pkgs;[
    git
    cudaPackages.cudnn
    inputs.nixgl.packages.${builtins.currentSystem}.default
  ];

  languages.python = {
    enable = true;
    package = pkgs.python3.withPackages (ps: with ps; [
      tensorflowWithCuda
    ]);
  };


  scripts.tftest.exec = ''
    nixGL python -c "import tensorflow as tf; print('Num GPUs Available:', len(tf.config.experimental.list_physical_devices('GPU')))"
  '';
}

Home-manager : gérer son $HOME par un seul fichier nix

home-manager

Utilise les modules de NixOS pour gérer avec nix la configuration perso d’un utilisateur

  • installation de paquetages
  • gestion des configurations (fichiers ~/.config, ~/.local et ~/.autre)
  • gestion des services utilisateurs
  • nombreux modules disponibles, mais il faut aller voir dans les sources

Utilisation basique

# ~/.config/home-manager/home.nix
{ config, pkgs, ... }:

{
home.username = "gamba";
  home.homeDirectory = "/home/gamba";
  home.stateVersion = "22.11";

  # Let Home Manager install and manage itself.
  programs.home-manager.enable = true;
}

Appliquer :

home-manager switch

Améliorer au fur et à mesure

{
  home.packages = [                               1
    pkgs.bat
    pkgs.jq
  ];

  programs.emacs = {                              2
    enable = true;
    extraPackages = epkgs: [
      epkgs.nix-mode
      epkgs.magit
    ];
  };

  services.gpg-agent = {                          3
    enable = true;
    defaultCacheTtl = 1800;
    enableSshSupport = true;
  };
}

Modèle déclaratif

home-manager permet ainsi de déclarer dans un fichier l’entièreté de la configuration de son environnement perso.

  • meilleur modèle que l’impératif nix profile install|remove
  • similaire à puppet/ansible, mais sans être root
  • module nixos facile à appréhender
  • bon marche-pied pour nixos

Démo

home.nix -> ajouter l’import du module devops.nix

module devops -> rajouter openshift et consorts

appliquer avec home-manager switch --flake .#gamba --impure

Intermédiaire : générer une image docker

Exemple : pour faire de l’intégration continue

pkgs.dockerTools

nix/zola-docker.nix

{ pkgs ? import <nixpkgs> {} }:

pkgs.dockerTools.buildLayeredImage {
  name = "zola-docker";
  tag = "latest";
  contents = with pkgs; [              #1
    bash
    coreutils  # ls, mkdir, rm …
    gnugrep
    zola
  ];
}

#1 : you can add any package from https://search.nixos.org

Construire l’image

nix-build ./nix/zola-docker.nix
# creates ./result, link to
realpath ./result
/nix/store/p5sf2bngqwvr45mq6jb8p6lppzgn5cym-zola.tar.gz

Importer dans l’instance docker locale

Comme tout .tar.gz, avec docker load :

docker load -i $(realpath ./result)

envoyer sur plmlab, utiliser avec pages : https://plmteam.pages.math.cnrs.fr/docs/public-zola-doc/utilisateurs/nix-integration-continue/

Usages avancées

plmlab:calcul/slurm-nvml

Objectif :

  • installer slurm par nix sur une debian, en utilisant les drivers nvidia installés par debian
  • overlay : surcharger toute ou partie d’une déclaration existante
  • flakes :
    • permet de fixer la version de nixpkgs
    • utilisation à distance par dépôt git : partage de code et redistribution
  • définition de service systemd

Exemples commentés

slurm-nvml/flake.nix

slurm-nvml-overlay.nix : on part d’un paquetage existant, et on surcharge

slurmctld-service.nix : utilise github:serokell/systemd-nix

Conclusion

Progression conseillée :

  • nix profile install|remove : manipulation à la apt install|remove
  • nix run|shell pour tester un logiciel trouvé sur https://search.nixos.org sans l’installer
  • devenv : environnement de projet partagé
  • home-manager puis nixos : utiliser des modules existants pour décrire une configuration
  • utilisation du langage nix obligatoire pour définir des nouveaux paquetages
    • images docker
    • modifier des paquetages existants