• Autore:   Elia Argentieri
  • Ultima modifica:   19 nov 2021 02:09
  • Redazione:   27 set 2021 22:00
  • Sorgente di questa pagina
  • Tempo di lettura:   6 minuti

Oggi vorrei parlarvi di una distribuzione GNU/Linux molto peculiare e interessante che ho iniziato ad utilizzare come mio sistema principale, ovvero NixOS.

Questa distribuzione GNU/Linux più unica che rara (in realtà anche GNU Guix è simile) utilizza il gestore di pacchetti nix e una configurazione dichiarativa, consentendo aggiornamenti di sistema affidabili.

Gestore di pacchetti nix

Il gestore di pacchetti nix fonda la sua logica attorno all’omonimo linguaggio funzionale lazy, appositamente progettato per la gestione di pacchetti. Come tutti i linguaggi funzionali, viene enfatizzata l’immutabilità delle strutture dati e la riduzione ai minimi termini degli “effetti collaterali”, cioè mutamenti dello stato del programma non espliciti. La valutazione lazy aiuta a ritardare il calcolo solo quando necessario e ad evitare di calcolare cose che non verranno effettivamente utilizzate nel programma.

Derivazioni

Il gestore di pacchetti nix è in grado di interpretare i programmi scritti in nix, chiamati derivazioni. Il risultato del calcolo di più derivazioni va a comporre un pacchetto vero e proprio. In nix ogni pacchetto ha le sue dipendenze pacchettizzate sotto forma di derivazioni che restano indipendenti le une dalle altre, permettendo l’installazione di software che richiedono versioni differenti della stessa libreria. Sotto questo aspetto, nix è anche simile ad un sistema di compilazione (build system) generalizzato (applicabile a qualsiasi linguaggio o piattaforma). Possiamo infatti simulare una virtualenv di python con una semplice derivazione che richiede le dipendenze necessarie.

Cache binaria

Il calcolo ripetuto di una derivazione dovrebbe produrre sempre lo stesso risultato, quindi i risultati calcolati possono essere salvati su disco per un uso futuro, per non dover ricalcolare sempre le stesse cose. Comunque ogni volta che si vuole installare un nuovo pacchetto, bisognerebbe calcolare le derivazioni che lo compongono e quindi andrebbero compilati i sorgenti dei software. Ma ciò richiede non poche risorse in termini di tempo ed energia. Ecco che entra in gioco la cache binaria del progetto nix. In pratica un server calcola per noi le derivazioni, che poi possono essere comodamente scaricate e installate da tutti gli utenti del mondo che vogliono usufruirne. Ovviamente, nel caso in cui abbiamo scritto una nostra derivazione, questa non si troverà in cache e dovrà essere comunque calcolata (e via con i compilatori…).

Queste caratteristiche di nix (l’insieme trino di gestore di pacchetti, linguaggio e sistema di compilazione) agevolano la riproducibilità dei pacchetti nix, cioè la possibilità di verificare che un dato pacchetto binario sia stato ottenuto da un dato sorgente e quindi che non ci siano state manipolazioni potenzialmente malevole all’interno del pacchetto.

NixOS

Altra caratteristica di nix, sfruttata a pieno da NixOS, è la possibilità di dichiarare in un file come deve essere fatto il nostro sistema: quali pacchetti rendere disponibili, come configurare i software, personalizzare qualsiasi aspetto, ecc. Questa configurazione centralizzata si trova in NixOS su /etc/nixos/configurations.nix e può essere messa in atto dal comando nixos-rebuild switch. Come si può intuire dall’estensione del file non si tratta che di una derivazione nix. Al termine del calcolo della derivazione, ci ritroveremo con un sistema già configurato esattamente come lo abbiamo dichiarato. Ciò consente di portare con sé questo file e di riprodurre lo stesso sistema lanciando un paio di comandi.

Generazioni

Per NixOS non c’è molta differenza tra una modifica della derivazione /etc/nixos/configurations.nix e un aggiornamento di sistema: entrambi sfruttano il concetto di generazione. Una generazione è il risultato finale del calcolo di tutte le derivazioni necessarie a comporre il nostro sistema ed è costituita da collegamenti simbolici che puntano ai risultati di queste derivazioni, cioè ai software correttamente versionati e configurati come richiesto. Al costo di occupare più spazio, i risultati del calcolo delle vecchie derivazioni non vengono sovrascritti, ma continuano ad essere puntati dalle vecchie generazioni. Quando accendiamo il pc, il boot manager di NixOS (può essere GRUB o systemd-boot) ci permette di scegliere quale generazione avviare. In caso di problemi con la nuova generazione, possiamo avviare il sistema da una generazione precedente che sappiamo essere valida.

Il GRUB di NixOS ci permette di scegliere la generazione da usare all'avvio
Il GRUB di NixOS ci permette di scegliere la generazione da usare all'avvio

Dopo un po’ di utilizzo è possibile che si accumulino troppe generazioni che occupano spazio sul disco rigido. A tal proposito ci aiuta il comando nix-collect-garbage, che è anche in grado di rimuovere le generazioni più vecchie e lasciare solo le più recenti.

Il nix store e alcuni svantaggi

NixOS non rispetta lo FHS (File-system Hierarchy Standard, lo standard che definisce come deve essere strutturato il file-system di un sistema operativo), in quanto le caratteristiche implementate da NixOS non sarebbero possibili. Il gestore di pacchetti nix, infatti, salva i risultati del calcolo delle derivazioni nel percorso non standard /nix/store/ e poi rende disponibile i vari pacchetti tramite un gioco di collegamenti simbolici. Se installiamo un pacchetto alla versione 1 e poi lo aggiorniamo alla versione 2, dentro a /nix/store/ possiamo trovare entrambe le versioni. L’aggiornamento avrà prodotto una nuova generazione che sarà composta da un collegamento simbolico alla nuova versione 2. La vecchia generazione continuerà a puntare alla versione 1.

Il Nix Store dal 1875 in Texas...
Il Nix Store dal 1875 in Texas...

In realtà il nix store assomiglia più ad una giungla di collegamenti simbolici:

Giungla di collegamenti simbolici su tela
Giungla di collegamenti simbolici su tela

Le frecce nell’immagine rappresentano i collegamenti simbolici. Nella cartella /nix/var/nix/profiles troviamo il profilo di sistema (sotto per-users troveremmo un collegamento per il profilo di ogni utente), ovvero il collegamento system. Tale collegamento punta alla generazione corrente, in questo caso la numero 71, che a sua volta punta ad una cartella dello store che contiene il collegamento sw che punta ad un’altra derivazione dello store che contiene i familiari etc, share, bin. Dentro bin troviamo i collegamenti ai vari eseguibili che sono stati installati nel sistema che, infine, si trovano effettivamente nella loro propria e univoca posizione nello store.

Il fatto di non rispettare il FHS implica che se lanciamo un programma esterno a nix che si aspetta di lavorare in un ambiente FHS, probabilmente fallirà. Tuttavia non dovrebbe essere difficile integrare il programma nell’ambiente nix e a volte è affettivamente necessario uscire dagli schemi e reinventare per progredire.

Conclusioni

Al momento ho un parere molto positivo su questa distribuzione GNU/Linux. Tutto sta funzionando egregiamente e sicuramente il tempo mi rivelerà quanto questa distribuzione sia affidabile e solida. Dopo aver installato NixOS, mi sono reso conto, grazie a repology.org, quanto sia esteso il catalogo di pacchetti nix con ben 64993 progetti disponibili al momento in cui scrivo. Tale numero risulta ancora più incredibile se comparato ad altre distribuzioni. L’unico repository che si avvicina a queste cifre è l’AUR (Arch User Repository), che però distribuisce soltanto i sorgenti dei pacchetti (i famosi PKGBUILD), mentre la cache binaria di nix distribuisce pacchetti binari pronti da installare e lascia disponibili anche tutte le versioni passate. Così facendo è possibile continuare a riprodurre sistemi che usano vecchi software senza dover ricalcolare le vecchie derivazioni. Pare che la cache risieda compressa su un server S3 che può arrivare fino a 220TB. Non ci sono problemi di spazio al momento.

Grazie per l’attenzione e buon distro-hopping.