Nix è il punto d’ingresso a un rabbit hole in cui sono cascato ormai anni fa e da cui non mi sono più ripreso. All’apparenza è un semplice package manager, ma in realtà rappresenta l’inizio del proprio declino cognitivo. Proprio per questo ti invito a proseguire nella lettura di queste note, perché scoprirai un nuovo mondo meraviglioso.

Un buon punto di partenza per capire cos’è esattamente Nix e come funziona tutto il suo ecosistema sono le Nix Pills, una serie di tutorial pensati per spiegare Nix in modo progressivo. Molti dei contenuti delle note riguardanti Nix nel mio Giardino Digitale sono presi dalle Nix Pills.

Non spiegherò qui nei dettagli come installare Nix (per quello c’è la documentazione ufficiale), ma piuttosto preferisco spiegarti cos’è e perché dovresti usarlo.

Introduzione a Nix

Ok, Nix è un package manager, ma cos’ha di speciale? Perché dovrei usarlo?

Pacchetti come derivazioni

Te lo spiego subito. Nel 2003, uno sviluppatore nederlandese di nome Eelco Dolstra progetta un nuovo package manager come progetto di ricerca presso l’Università di Utrecht, nei Paesi Bassi. Qui nasce l’idea di Nix che qualche anno dopo verrà approfondita nella sua tesi di dottorato del 2006, dal titolo The Purely Functional Software Deployment Model (disponibile qui), in cui Dolstra descrive un approccio che punta a risolvere i problemi degli approcci tradizionali alla distribuzione di software, come la mancanza di dipendenze o l’interferenza tra dipendenze.

Per farlo, Dolstra utilizza un semplice ma geniale trucco: ogni pacchetto viene isolato in una cartella a se stante e, anziché conservare il pacchetto vero e proprio, il sistema operativo si salva una sua “descrizione”, detta derivazione, che specifica come costruire il pacchetto, incluse le sue dipendenze.

Le derivazioni sono espresse (o meglio, dichiarate) sotto forma di funzioni che prendono in input le dipendenze del pacchetto in questione e il cui risultato è l’installazione del pacchetto nel sistema operativo.

Questo metodo sfrutta i vantaggi sia del paradigma dichiarativo che di quello funzionale. I pacchetti sono rappresentati sotto forma di funzioni e una delle proprietà del paradigma funzionale è proprio il determinismo, per cui una funzione, dati determinati argomenti in input, produce sempre gli stessi risultati.

Ecco perché Nix è una delle scelte migliori nell’ambito della distribuzione del software.

Definizione: derivazione

In Nix, una derivazione è una descrizione dichiarativa della build di un pacchetto, espressa sotto forma di una funzione che prende come input le dipendenze del pacchetto e il cui risultato è l’installazione del pacchetto nel sistema operativo.

Una derivazione è racchiusa in una cartella il cui nome è del formato

<hash>-<nome>

dove:

Ciò significa che Nix non lavora direttamente sui pacchetti, ma su come ottenere quei pacchetti dal loro codice sorgente.

Attenzione: derivazione e pacchetto come sinonimi

Pur non essendo esattamente la stessa cosa, in queste note potrei usare per comodità i termini derivazione e pacchetto come sinonimi.

Il Nix store

Le derivazioni sono raccolte nel Nix store (dove il termine store va inteso non come negozio, ma come deposito).

Definizione: Nix store

Il Nix store è una cartella del sistema operativo (solitamente /nix/store) in cui Nix memorizza tutte le derivazioni al suo interno.

Esempio di derivazione nel Nix store

Prendiamo come esempio una derivazione di bash contenuta nel Nix store:

/nix/store/s4zia7hhqkin1di0f187b79sa2srhv6k-bash-4.2-p45/

All’interno di questa cartella potremo trovare il binario di bash, ossia il /bin/bash che conosciamo tutti, al percorso

/nix/store/s4zia7hhqkin1di0f187b79sa2srhv6k-bash-4.2-p45/bin/bash

Ogni volta che vorremo usare il programma bash, dovremo far riferimento a questo binario presente nel Nix store.

Ovviamente, per rendere questi programmi comodi da usare, Nix si occupa di far comparire i binari nel tuo PATH nel modo appropriato.

Ciò evita anche il problema di avere pacchetti sparsi per tutto il file system: se stiamo cercando un pacchetto (o meglio, in questo caso una derivazione, sappiamo che la troveremo sicuramente nel Nix store).

In sostanza, quello che abbiamo è un archivio (il Nix store) di tutti i pacchetti (sotto forma di derivazioni), a volte anche con versioni multiple ma distinte (grazie all’univocità della derivazione).

Osservazione: comportamento di Nix con le dipendenze

Come si comporta Nix per le dipendenze? Nix si assicura di collegare a ogni derivazione le proprie dipendenze, a loro volta gestite tramite altre derivazioni.

Mi spiego meglio: facciamo finta che io stia usando bash con la versione 5.2.26 che ha come dipendenza glibc versione 2.42. Grazie all’indipendenza tra le derivazioni, posso decidere di usare nello stesso sistema operativo anche bash 5.2.27 che ha come dipendenza glibc versione 2.43. Allo stesso modo, potrei usare contemporaneamente un modulo di Python 2.7 compilato con gcc 4.6 e lo stesso modulo ma scritto in Python 3 compilato con gcc 4.8.

In altre parole, Nix offre solo dipendenze “dirette” da una derivazione a un’altra derivazione.

Insomma, Nix ti permette di usare pacchetti e configurazioni in modo isolato, riproducibile e senza conflitti e gestendo più versioni dello stesso software contemporaneamente. Rappresenta un deus ex machina per chi ha sempre voluto un sistema in cui la gestione di pacchetti e delle loro dipendenze non sono un incubo.

Definizione: package manager Nix

Nix è un package manager per sistemi UNIX-like, ideato dallo sviluppatore nederlandese Eelco Dolstra, in cui ogni pacchetto è rappresentato da una derivazione che determina come costruirlo e il cui risultato viene memorizzato nel Nix store che garantisce isolamento, immutabilità e univocità delle derivazioni stesse.

Osservazione: parallelismo tra i package manager e i linguaggi di programmazione

Nix sta ai pacchetti come linguaggi a basso livello come il C stanno alla memoria:

  • come “contenitore”, al posto della RAM, abbiamo lo spazio sul disco;
  • come oggetti su cui operare, anziché variabili, abbiamo le derivazioni;
  • per accedere a questi oggetti, anziché indirizzi, abbiamo i percorsi delle derivazioni;
  • per riferirsi a questi oggetti, anziché usare i puntatori, accediamo alle derivazioni tramite i loro percorsi e, al posto dei dangling pointer, abbiamo percorsi che fanno riferimenti a derivazioni inesistenti;
  • per manipolare questi riferimenti, anziché l’aritmetica dei puntatori, abbiamo le operazioni su stringhe che rappresentano i percorsi delle derivazioni;
  • come struttura dati per gestire il tutto, anziché avere un directory tree, abbiamo un dependency tree;
  • e così via.

Allo stesso modo, linguaggi che non hanno una gestione strutturata dei puntatori, come Assembly, è comparabile ai package manager tradizionali in cui i file dei pacchetti sono disorganizzati e sparsi per tutto il file system.

Il Nixpkgs

La lista dei pacchetti che Nix ha a disposizione è contenuta nel Nixpkgs.

Definizione: Nixpkgs

Il Nixpkgs (pronuncia: Nix packages) è la collezione di pacchetti disponibili per il package manager Nix.

Su GitHub si può trovare il repository completo, disponibile qui.

Nixpkgs, al momento in cui sto scrivendo questa nota (gennaio 2026), è il repository di pacchetti più grande al momento, con oltre 120.000 pacchetti disponibili.

I pacchetti all’interno del Nixpkgs sono divisi in canali.

Definizione: canale

In Nix, un canale è una collezione di determinate versioni dei pacchetti disponibili nel Nixpkgs.

Osservazione: incompatibilità tra canali

I canali possono generare alcuni problemi: computer diversi potrebbero usare canali diversi (oppure stessi canali) e, di conseguenza, non avere a disposizione le stesse versioni degli stessi pacchetti.

Questo problema viene risolto attraverso i flake.