Cachix, un service de cache binaire basé sur Nix

Voir aussi : journal linuxfr - vidéo youtube - vidéo peertube

Cachix permet de gérer facilement un cache personnel de paquets binaires. Concrètement, il s’agit d’un service de cloud et d’un logiciel client, le tout basé sur le gestionnaire de paquets Nix. Cachix propose différentes offres, dont une offre gratuite de 10 Go de stockage en accès public.

Quand on utilise la logithèque officielle de Nix, on télécharge des paquets binaires déjà compilés. Nix permet très facilement d’empaqueter des programmes/bibliothèques personnels ou de modifier les paquets officiels. Mais dans ce cas, les paquets binaires correspondants ne sont pas dans le cache officiel et doivent donc être compilés sur la machine locale. Cachix permet d’envoyer les paquets binaires ainsi compilés sur un serveur. On peut alors récupérer ces paquets sur d’autres machines sans avoir à recompiler.

Exemple de cas d’utilisation

Imaginons qu’on a développé une bibliothèque personnelle tuto38lib, potentiellement longue à compiler, et qu’on l’utilise désormais pour développer un projet tuto38appli. Ces deux projets sont empaquetés via Nix si bien qu’on peut intégrer tuto38lib dans tuto38appli avec le fichier tuto38appli/default.nix suivant :

{ pkgs ? import <nixpkgs> {} }:

let 

  tuto38lib-src = fetchTarball {
    url = "https://gitlab.com/nokomprendo/tuto38lib/-/archive/v1.0/tuto38lib-v1.0.tar.gz";
    sha256 = "1di8ms0g1j9kih9qg1s42p9wi5xxbm7h3n9as6fbxqfbfa75w9nf";
  };

  tuto38lib = pkgs.callPackage tuto38lib-src {};

in pkgs.stdenv.mkDerivation {
  name = "tuto38appli";
  src = ./.;
  buildInputs = with pkgs; [ cmake tuto38lib ];
}

Pour travailler sur le projet tuto38appli, il suffit de récupérer le code et de lancer un nix-shell. Toutes les dépendances sont récupérées et on peut alors travailler sur le projet. Ici il s’agit d’un projet C++/Cmake :

$ nix-shell 
these derivations will be built:
  /nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv
building '/nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv'...
unpacking sources
...

[nix-shell]$ mkdir build

[nix-shell]$ cd build/

[nix-shell]$ cmake ..
...

[nix-shell]$ make
...

[nix-shell]$ ./tuto38appli 
42

[nix-shell]$ exit

On constate que pour tuto38lib, le code source est récupéré, compilé et installé sur la machine locale, dans le /nix/store. Ainsi, si on lance de nouveau un nix-shell utilisant tuto38lib, cette bibliothèque est déjà sur le système local et n’est donc pas recompilée.

$ find /nix/store -maxdepth 1 -name "*tuto38lib*"
/nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv
/nix/store/js0gbdilqjg3y9yhpjfc7slja902kfxy-tuto38lib

$ nix-shell 

[nix-shell]$ 

Si on nettoie les paquets de tuto38lib dans le /nix/store ou qu’on passe une autre machine, tuto38lib n’est plus disponible. Si on lance un nix-shell dans le projet tuto38appli, la bibliothèque tuto38lib est donc de nouveau téléchargée, compilée et installée.

$ find /nix/store -maxdepth 1 -name "*tuto38lib*" -exec nix-store --delete {} \+
finding garbage collector roots...
deleting '/nix/store/js0gbdilqjg3y9yhpjfc7slja902kfxy-tuto38lib'
deleting '/nix/store/h85xxfmc0lf5g8srhv7jqr8kbjdijia1-tuto38appli.drv'
deleting '/nix/store/ss39dl3l4y0kbccpkjzr4dbypr0fz5c2-tuto38appli.drv'
deleting '/nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv'
deleting '/nix/store/trash'
deleting unused links...
note: currently hard linking saves -0.00 MiB
4 store paths deleted, 0.02 MiB freed

$ nix-shell 
these derivations will be built:
  /nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv
building '/nix/store/zasgjbqnp89nnzb3fyrvi0daq2bwnacq-tuto38lib.drv'...
unpacking sources
...

[nix-shell]$ 

Cachix permet de mettre les paquets binaires produits par la première compilation sur un serveur et de récupérer ensuite ces paquets sans avoir à les recompiler.

Installation du client cachix

Sur NixOS, ceci est assez simple. Il suffit d’éditer le fichier /etc/nixos/configuration.nix pour ajouter le paquet cachix et spécifier l’utilisateur (ici nokomprendo) dans les trustedUsers :

  environment.systemPackages = with pkgs; [
    cachix
    ...
  ];

  nix.trustedUsers = [ "nokomprendo" "root" ];

Il faut ensuite mettre à jour la configuration du système :

$ sudo nixos-rebuild switch

Et, éventuellement, nettoyer le cache du root :

$ sudo rm -rf /root/.cache/nix

Création d’un dépôt de cache

Tout est expliqué sur le site de cachix. Il faut d’abord se connecter (via un compte github) puis créer un dépôt de cache (par exemple, tuto38).

On génère ensuite une clé d’authentification du dépôt :

cachix authtoken ...
...

Et une clé de signature :

$ cachix generate-keypair tuto38
...

Mettre en cache des paquets

La commande cachix push permet d’envoyer dans un cache, un paquet local et ses dépendances :

$ cachix push tuto38 /nix/store/js0gbdilqjg3y9yhpjfc7slja902kfxy-tuto38lib
pushing /nix/store/4l35nqpaiwzhfafrpby1xf7kfik7ai7c-gcc-8.3.0-lib
...

Utilisation du cache

La commande cachix use indique à Nix qu’il faut regarder dans un dépôt de cache si un paquet binaire n’est pas déjà disponible.

$ cachix use tuto38

Par exemple, avec le projet tuto38appli précédent, si on nettoie l’installation locale de tuto38lib et qu’on lance de nouveau un nix-shell, c’est désormais le paquet binaire qui est directement téléchargé du cache et installé sur la machine.

$ find /nix/store -maxdepth 1 -name "*tuto38lib*" -exec nix-store --delete {} \+
...

$ nix-shell 
these paths will be fetched (0.00 MiB download, 0.02 MiB unpacked):
  /nix/store/js0gbdilqjg3y9yhpjfc7slja902kfxy-tuto38lib
copying path '/nix/store/js0gbdilqjg3y9yhpjfc7slja902kfxy-tuto38lib' from 'https://tuto38.cachix.org'...

[nix-shell]$ 

Conclusion

Cachix permet de mettre en cache des paquets binaires Nix pour pouvoir les récupérer ultérieurement sans avoir à les recompiler. Il est très pratique pour récupérer plus rapidement des paquets personnels ou des paquets officiels modifiés, par exemple pour mettre en place un environnement logiciel local ou pour optimiser un processus d’intégration continue. Dans un environnement Nix, cachix est facile à mettre en place et à utiliser. Enfin, il est assez complémentaire avec Hydra, qui permet de dérouler une intégration continue et de générer des paquets binaires mais qui est plus difficile à mettre en place.