Configurazione come dati
Quando un aggiornamento di Arch, un martedì mattina, richiede una nuova soluzione alternativa per una specifica iGPU Intel – che cosa fa un programma di installazione tradizionale? Nulla, finché qualcuno non corregge lo script bash su cui si basa, pubblica una nuova ISO (1–3 GB) e aspetta che gli utenti la scarichino. Nel migliore dei casi giorni, più spesso settimane.
Ditana adotta un approccio radicalmente diverso: la configurazione come dati.
Tre parti separate
Sezione intitolata «Tre parti separate»L’architettura di Ditana è suddivisa in tre repository:
-
Il motore (
ditana-installer) – un programma piccolo e generico che sa come disegnare finestre di dialogo, partizionare dischi, rilevare l’hardware ed eseguirepacstrap. -
La base di conoscenza (
ditana-config) – un database strutturato scritto in KDL v2. Dichiara ogni impostazione, ogni particolarità dell’hardware, ogni dipendenza tra pacchetti, ogni script del ciclo di vita e le relazioni logiche tra di essi. -
La pipeline dei pacchetti (
ditana-build) – ciò che compila i pacchetti indicati dalla base di conoscenza. Il repository di Ditana si appoggia su quello di Arch, e le ricette che contiene vengono ricompilate dai sorgenti, sottoposte a revisione e firmate da questa pipeline, anziché essere prese così come arrivano.
Quando avviate l’ISO di Ditana, il motore si collega a GitHub e scarica l’ultima versione della base di conoscenza (ripiegando su uno snapshot offline incluso nell’ISO se non avete una connessione a Internet).
Vale la pena sapere anche che cosa non copre il download al momento dell’esecuzione. Il motore stesso e il convertitore con cui legge il KDL si trovano sul supporto e cambiano solo con un supporto nuovo. E il canale trasporta un errore con la stessa facilità di una correzione: una configurazione che indica un pacchetto che il repository di un supporto più vecchio non è in grado di fornire fa sì che con quel supporto non si possa più installare, ed è esattamente ciò che è successo quando Arch ha ritirato bubblewrap-suid a settembre 2026.
Perché è importante
Sezione intitolata «Perché è importante»Tre vantaggi, in ordine di impatto immediato:
- Aggiornamenti senza ricreare l’ISO. Se un utente segnala che un recente aggiornamento di Arch richiede una nuova soluzione alternativa, la correzione arriva in
ditana-configcome piccola modifica KDL. Già la persona successiva che avvia un’ISO di Ditana scarica automaticamente la logica aggiornata. La correzione raggiunge gli utenti immediatamente, senza che nessuno debba scaricare una nuova ISO. - Motivazioni trasparenti. Poiché le impostazioni sono dichiarate come dati strutturati con condizioni esplicite, le regole sono verificabili da un capo all’altro. Chiunque può leggere i file KDL e vedere esattamente perché un pacchetto viene installato, quale combinazione di impostazioni fa sì che venga installato un file di configurazione, o quale proprietà dell’hardware determina la disponibilità di un’opzione. Nessun lavoro investigativo negli script bash.
- Contributi tramite fork. Aggiungere una soluzione alternativa per l’hardware, un nuovo ritocco al desktop o una nuova scelta di pacchettizzazione comporta di solito la modifica di un solo file KDL. Nessuna modifica al motore del programma di installazione – e, a parte i rilevatori dell’hardware, che sono espressioni Raku di una sola riga, nessun codice Raku. Il README di
ditana-configguida chi contribuisce attraverso lo schema; la maggior parte delle pull request riguarda un solo file.
Perché KDL e non JSON o YAML
Sezione intitolata «Perché KDL e non JSON o YAML»La base di conoscenza avrebbe potuto usare qualsiasi formato strutturato. È stato scelto KDL perché ha le proprietà di cui la configurazione di Ditana ha effettivamente bisogno:
- Commenti nativi. YAML e JSON sono entrambi in difficoltà su questo punto – YAML ha i commenti, ma il supporto degli strumenti è disomogeneo; JSON non li ha affatto. Le impostazioni di Ditana includono ampi commenti che spiegano perché un valore predefinito è quello che è. Quei commenti sono proprio l’essenziale.
- Stringhe grezze. I frammenti di shell incorporati, le espressioni sed e le espressioni regolari sono supportati a pieno titolo. Nessun doppio escape di
"e\per accontentare il parser. - Gerarchico senza formalità. Nodi figli, proprietà e argomenti coesistono in modo pulito. Lo stesso nodo può descrivere un’impostazione e contenere nodi subordinati per i suoi pacchetti, script e file.
- Facile da confrontare. L’ordine di inserimento viene mantenuto. La revisione del codice di un’aggiunta di una riga mostra una differenza di una sola riga, non una struttura riordinata.
Il formato viene analizzato da un piccolo convertitore in Rust (json-kdl-converter, anch’esso sotto controllo di versione accanto allo schema) prima che il programma di installazione in Raku lo utilizzi come JSON. La sezione successiva spiega come i dati vengono convalidati da un capo all’altro prima di tutto ciò.
Come si presenta in pratica
Sezione intitolata «Come si presenta in pratica»Un’impostazione completa e funzionante in ditana-config ha questo aspetto:
// XFCE fallback for Wayland-only primary terminals (foot, cosmic-term).// Fires when the user picks a Wayland-native terminal AND also installs// XFCE. Writes to xfce-xdg-terminals.list only; xdg-terminals.list still// points at the primary terminal for Wayland sessions.- name="fallback-kitty-for-xfce" \ default-value="`(install-foot OR install-cosmic-term) AND install-xfce`" { arch-packages "kitty" \ "imagemagick" \ "python-pygments" \ "libcanberra" \ "xdg-terminal-exec-git" files "/etc/xdg/kitty/kitty.conf" \ "/usr/share/pixmaps/ditana-logo-tiny.png" chroot-script "mkdir -p /etc/xdg" \ "echo kitty.desktop >/etc/xdg/xfce-xdg-terminals.list"}Quel nodo dichiara un’impostazione derivata senza una finestra di dialogo propria, un’espressione logica su altre tre impostazioni, i pacchetti da installare quando l’espressione è vera e il file che fa sì che XFCE li usi. La motivazione sta accanto alla regola, dove chi la esamina può vederne il perché. La documentazione completa dello schema si trova nel README di ditana-config.
La stessa struttura trasporta cose che non sono affatto pacchetti. Un programma che ha bisogno di uno user namespace (spazio dei nomi utente) non privilegiato per la propria sandbox lo dichiara direttamente accanto a sé:
- name="flatpak" default-value=#true { arch-packages "flatpak" // Every Flatpak, not only the browsers, runs bwrap to build its outer // sandbox, and bwrap needs a user namespace. This is the declaration // that buys it one. userns-allow "/usr/bin/bwrap" }Ditana non concede gli user namespace non privilegiati a ogni programma. Un programma BPF minimo, ditana-userns-guard, è agganciato all’hook userns_create del kernel stesso e rifiuta un namespace a qualsiasi eseguibile per il quale nessuna impostazione lo abbia richiesto. Un hook di questo tipo può solo rifiutare e mai concedere, motivo per cui il sysctl che disattiva i namespace viene innalzato solo una volta caricato il programma – una macchina che non riesce a caricarlo li lascia completamente disattivati. È lo stato predefinito di un’opzione di System Hardening; se la disattivate, i namespace sono aperti a tutto, come nella maggior parte delle distribuzioni.
Ditana rifiuta gli user namespace a tutto ciò che non li ha chiesti. Ciò che rende praticabile questo approccio è che la richiesta è locale: viene scritta dove viene scelto il pacchetto, per cui non serve mantenere sincronizzato un elenco centrale, e disattivando l’impostazione se ne va anche l’autorizzazione. Il programma di installazione raccoglie le dichiarazioni delle impostazioni che alla fine restano attive e genera da queste l’elenco degli eseguibili consentiti.
Convalida: intercettare gli errori prima che vengano distribuiti
Sezione intitolata «Convalida: intercettare gli errori prima che vengano distribuiti»Una base di conoscenza così grande ha bisogno di barriere di protezione. A ogni commit – sia localmente tramite hook pre-commit, sia in remoto su GitHub Actions – viene eseguita una pipeline di convalida a più livelli che intercetta gli errori che potrebbero sfuggire a una persona che esegue la revisione:
- Sintassi KDL (
kdlfmt) – innanzitutto, che il file sia analizzabile. - Convalida dello schema (
ditana-schema.json) – ogni campo ha il tipo corretto, nessuna proprietà sconosciuta, nessun campo obbligatorio mancante. Intercetta errori di battitura nei nomi dei campi, comearc-packagesinvece diarch-packages. - Integrità dei riferimenti ai file – ogni file a cui un’impostazione fa riferimento esiste effettivamente in
folders/; viceversa, a ogni file infolders/fa riferimento almeno un’impostazione. I file orfani vengono segnalati. I riferimenti a directory (che silenziosamente non farebbero nulla, perché il programma di installazione usacpsenza-R) vengono rifiutati. - Correttezza del ciclo di vita – le righe di
chroot-scriptche toccano/etc/skel/vengono rifiutate, perché l’utente viene creato dopo l’esecuzione dichroot-script– il campo corretto èearly-chroot-script. Un bug subdolo che altrimenti produrrebbe un sistema in cui la directory home del nuovo utente non contiene i file previsti. - Validità degli script di shell – ogni frammento di shell in uno qualsiasi dei campi che contengono elenchi di script viene sottoposto a
bash -nper la sintassi e ashellcheckper la qualità. Una virgoletta mancante o un bug del tipo[ "$x" = $y ]viene rilevato al momento del commit, non alla prima installazione. - Autorizzazioni e impostazioni del kernel dichiarate – una voce
userns-allowdeve essere un percorso assoluto, e una vocesysctldeve indicare qualcosa che sia una chiave sysctl e assegnarle un valore che il kernel accetti. Entrambi i campi sono stati aggiunti nella 0.9.4 e sono dichiarati inditana-schema.json. - Impostazioni del kernel in contraddizione – due impostazioni che scrivono la stessa chiave sysctl con valori diversi interrompono l’installazione, e il messaggio le nomina entrambe. Quando il tutto veniva assemblato come testo di shell, come accadeva prima della 0.9.4, vinceva semplicemente l’ultima riga scritta e nessuno ne veniva informato.
- Integrità delle espressioni logiche – gli apici inversi devono essere bilanciati; ogni nome di impostazione a cui si fa riferimento in un’espressione
default-valueoavailabledeve esistere effettivamente da qualche parte nella base di conoscenza. Un errore di battitura comeinstall-cosmikinvece diinstall-cosmicviene intercettato al momento del commit, anziché provocare un arresto anomalo silenzioso durante l’esecuzione.
Il controllo completo viene eseguito localmente in pochi secondi con pre-commit run --all-files, e di nuovo a ogni push su GitHub. Se è verde in locale, è verde anche nella CI; i commit difettosi non arrivano mai in una versione pubblicata.
Per approfondire
Sezione intitolata «Per approfondire»- Leggete come le impostazioni dipendono le une dalle altre –
availableedefault-valuesono il luogo in cui risiede la logica della base di conoscenza. - Consultate il repository
ditana-configper vedere come le regole sono organizzate per finestra di dialogo e per argomento. - Leggete il README di
ditana-configper il modello dei dati: come si relazionano impostazioni, script, finestre di dialogo e file. - Consultate il codice sorgente di
ditana-installerse volete vedere il motore che legge la configurazione e agisce di conseguenza.
Questa traduzione è stata realizzata automaticamente. I lettori la migliorano su Weblate.