Un rack server bloccato in un data center buio, un fascio di connessione SSH che raggiunge un lucchetto di cifratura luminoso

LUKS remoto? Pfft. Ecco come sbloccare via SSH una root ZFS cifrata su FreeBSD (nel modo difficile)

Se usi FreeBSD come me, su un server remoto con cifratura completa del disco (ZFS su GELI), conosci il panico del riavvio. Sei sempre alla mercé di un KVM-over-IP o di una connessione VNC dal browser, per inserire la password del filesystem root al prompt del kernel.

Inoltre, se (come me) fai girare un sistema con kern.securelevel > 0, allora installare una nuova libc significa riavviare in single user e installare gli aggiornamenti tramite la suddetta connessione KVM o VNC, che non è ergonomica per usare un eufemismo.

La soluzione standard è di solito un ambiente SSH pre-boot. Su Linux, dropbear-initramfs rende la cosa banale. Su FreeBSD? Devi costruirti un mfsroot (memory file system) custom da zero.

La maggior parte delle guide suggerisce di usare un semplice shell script come init. Funziona, ma è misero. Perdi il job control (niente Ctrl+C), non hai un TTY decente, e in bocca al lupo se devi fare debug dei problemi di rete in modo interattivo.

Non volevo un hack raffazzonato. Volevo un ambiente vero. Volevo init, getty, login, autenticazione PAM, e un chroot ZFS per la manutenzione – per installare aggiornamenti.

Root cifrata con LUKS su Raspberry PI 5

Un Raspberry Pi 5 su una scrivania con un SSD raffigurato come una cassaforte luminosa, un lucchetto che fluttua sopra

Premessa

Quindi ho cominciato a far girare Home Assistant a casa su un Raspberry PI 5 e ho semplicemente installato HAOS su una SD. Poi ho iniziato a sentirmi sempre più a disagio nel salvare credenziali nel filesystem di HA in chiaro (qualsiasi offuscamento non è sufficiente).

Considerando che configurare una root cifrata con HAOS è semplicemente impossibile senza forkarlo, e considerando anche che dedicare un intero RPI5 a HAOS è uno spreco di risorse, ho deciso di aggiungere un SSD al Pi, avviarlo con Raspbian e poi far girare HAOS dentro una VM.

In questo modo, posso avere una root cifrata sull’host principale, cifrando così l’intera VM HAOS.

Inoltre posso ora fare snapshot dell’intera VM HAOS e ho molta più flessibilità nella gestione. Ultimo ma non meno importante, posso anche usare la CPU e la RAM rimanenti del RPI per qualcos’altro.

Ringraziamenti

Prima di tutto, un grande grazie a questo post che mi ha dato le indicazioni iniziali su come fare il setup. Ma quel post del 2021 è ora leggermente datato, e molti passaggi non sono più necessari.

Secondo, un grande grazie a Eric Fjøsne per aver usato questa guida e averla corretta dato che l’avevo scritta perlopiù a posteriori :-).

Logo MetalOS

Ho presentato un talk ad All Systems Go 2025, la conferenza fondamentale sullo userspace Linux. La conferenza è organizzata principalmente dal team di systemd, ed è un punto d’incontro annuale per tutti quelli che lavorano su software di sistema Linux.

Il tema di quest’anno è stato prevalentemente “container, container, container”, con molte nuove funzionalità in systemd per supportare la containerizzazione e anche esperienze pratiche da persone che lavorano sul campo su come usano systemd e software collaterali per costruire infrastrutture a container.

Ho presentato insieme al mio collega Serge Dubrouski il nostro lavoro nella costruzione di un sistema operativo alla scala di Meta. Gestiamo un sistema operativo basato su immagini, ma l’azienda viene da due decenni di aggiornamenti del SO online, quindi abbiamo dovuto progettare una strategia di migrazione adeguata e gettare le fondamenta per il futuro.

Descriviamo come prepariamo le release CentOS dall’upstream, gli strumenti OSS che abbiamo costruito per creare le immagini del SO, e la tecnologia interna (MetalOS) che abbiamo ideato per costruire un SO che gira su milioni di server Linux.

Il logo: è metal perché MetalOS gira su bare metal, e le corna sono un riferimento ad AntlirANoTher Linux Image buildeR — il build system open-source che usiamo per produrre le immagini del SO.

Slide

📄 Scarica le slide (PDF, 482KB)

Il tuo browser non può visualizzare PDF incorporati. Scarica le slide qui.

Video

Puoi anche scaricare il video per la visione offline.

pfasciilogd: collegare pf e fail2ban

Una fortezza di regole firewall luminose con Beastie di guardia, che respinge i port scanner con un martello del ban

TL;DR

FreeBSD: come bloccare i port scanner dall’enumerare le porte aperte sul tuo server, usando fail2ban e una rappresentazione ASCII dei log di pf.

Premessa

Uso fail2ban per tenere alla larga attaccanti e bot che tentano di scansionare i miei siti web o di forzare le mie caselle di posta. Fail2ban funziona scansionando i file di log alla ricerca di pattern specifici e mantenendo un conteggio delle corrispondenze per IP, e permette all’amministratore di sistema di definire cosa fare quando quel conteggio supera una soglia definita.

I pattern sono indicativi di attività malevola, come il tentativo di indovinare la password di una casella di posta, o il tentativo di scansionare lo spazio di un sito web alla ricerca di vulnerabilità.

L’azione da eseguire nella maggior parte dei casi è bloccare l’indirizzo IP incriminato tramite il firewall della macchina, ma fail2ban supporta qualsiasi meccanismo che tu possa concepire, purché possa essere attuato da un comando UNIX.

PF e i suoi log

Sul mio server FreeBSD uso l’eccellente pf, il packet filter, per gestire il traffico in entrata e per eseguire la normalizzazione del traffico.

Root cifrata su ZFS con FreeBSD

Un server FreeBSD cifrato avvolto in scudi traslucidi, il cloud AWS che si sgretola sullo sfondo

Premessa

Nel 2023, gestisco ancora il mio mailserver. Sì, perché mi piace avere il controllo (almeno in parte) della mia vita digitale, e mi piace avere diversi nomi di dominio su cui tenere le mie cose. Tuttavia, stavo pagando 30€/mese ad AWS per avere in cambio 2 core, 2GiB di RAM e 40G di disco, appena sufficienti per far girare IMAP+SMTP+MySQL+Clamd, figurarsi qualsiasi forma di protezione antispam o ricerca full-text nel corpo delle email.

Insomma, stavo pagando un botto di soldi per far girare un servizio merdoso, e avevo persino pensato di chiudere tutto e spostare la posta e i siti web su qualche servizio completamente managed.

Però voglio ancora farlo

Beh, per ospitare quattro domini con solo qualche redirect email più i siti web che gestisco, avrei speso di più di quanto stavo già pagando, incatenandomi per di più a qualche fornitore di servizi e alle sue politiche.

Quindi, volevo usare FreeBSD e ho cominciato a cercare nella pagina degli ISP fino a decidere di valutare Hetzner e netcup, che offrono entrambi prezzi aggressivi e un buon vecchio VPS senza fronzoli.

Scelta del provider

Alla fine, ho scelto un netcup VPS 1000 che mi dà, a 1/3 del prezzo che pagavo ad AWS, 4 volte le risorse: 6 core, 8GiB di RAM, 160GiB di SSD RAID10 e un’installazione FreeBSD completamente libera e senza limitazioni.

Mi è stato affidato il compito di integrare l’autenticazione a due fattori con token hardware di OneSpan (ex VASCO) in uno stack Ruby — wrappando il loro SDK C proprietario VACMAN Controller per la validazione OTP in locale, e costruendo un client per l’API SOAP del OneSpan Authentication Server (originariamente chiamato Identikey Authentication Server, rinominato a metà progetto). Nessuno dei due aveva una libreria Ruby.

Per vacman_controller c’era un punto di partenza: una C extension Ruby di Marcus Lankenau che wrappava l’SDK AAL2. Un solo commit, nessuna release, parecchio grezza, ma le fondamenta — linking, import dei token e wrapper di base — c’erano. L’ho forkata in IFAD, sistemata, estesa e le ho spinto sopra 97 commit aggiuntivi. 14 release, dalla v0.1.0 alla v0.9.3.

Per identikey non c’era nulla — OneSpan distribuisce un SDK Java, nessuna libreria Ruby esiste. L’ho scritta da zero: 123 commit, 18 tag, dalla v0.2.0 alla v0.9.1.

Entrambe sono su GitHub. Ecco cosa c’è dentro.

🔍
Retrospettiva 2026
La mia ultima release e’ stata la v1.2.2 a maggio 2019. Dopo, Geremia Taglialatela ha preso in mano la manutenzione e l’ha portato alla v5.0.0 con supporto per Rails 8.1 e Ruby 4.0. 34 release in 14 anni, 201 stelle, e ancora attivamente mantenuta. La documentazione API e il repo sono entrambi vivi.

Sette anni fa ho rilasciato ChronoModel v0.1.0 — una gem Ruby che da’ ai modelli ActiveRecord capacita’ temporali su PostgreSQL. Cinque giorni di hacking, trentasei commit, nessun test, e una confessione sul monkey-patching della costante dell’adapter PostgreSQL.

Oggi taggo la v1.0.0. Il messaggio di commit e’ :gem: this is v1.0.0. Non proprio un discorso memorabile, ma il codice parla da solo: 506 commit, 31 release, 52 file modificati, 5.392 righe aggiunte. L’idea di base — viste aggiornabili su public, dati correnti su temporal, storico su history con table inheritance — non e’ mai cambiata. Tutto il resto si'.

🔍
Retrospettiva 2026
Il repo a github.com/ifad/translation-memory è ancora pubblico, ancora senza README, e il fork di Pontoon a cui parla resta privato. L’upstream di Mozilla è aperto e molto vivo. Se qualcuno all’IFAD usi ancora Pontoon otto anni dopo, sinceramente non lo so — l’ho costruito per un progetto sulla mia scrivania, non come cambio di workflow aziendale. La regex che strippa i caratteri non-word ha fatto il suo lavoro per i mesi in cui mi serviva. Poi, presumibilmente, la successiva migration dello schema di Pontoon ha rotto qualcosa. È quello che succede alle integrazioni che parlano direttamente con un database.

L’IFAD è un’agenzia ONU che opera in inglese, francese, spagnolo e arabo. Ogni stringa visibile delle nostre app Rails deve esistere in quattro lingue, il che significa che abbiamo un team di traduzione, il che significa che abbiamo un workflow di traduzione, che sulla maggior parte dei progetti prevede un CAT desktop, file allegati alle email, e translation memory che girano in formato XML.

Quel workflow non sopravvive a un progetto su cui sto lavorando in questo momento. È un’app web Rails con una scadenza stretta, le stringhe sorgente cambiano ogni settimana, e nel tempo che un traduttore impiega per finire un file TM e rimandarlo via email le stringhe si sono già spostate. Mi servono traduttori e sviluppatori che guardano lo stesso database in tempo reale. Scelgo Mozilla Pontoon — open-source, gratis, adattabile, scritto in Django, basato su Postgres — e lo tiro su per il mio progetto. La fregatura: c’è un corpus di traduzioni dal tool precedente che voglio usare per fare il seed di Pontoon dal primo giorno, così i traduttori non partono dal nulla.

Oggi inizio un repo translation-memory e scrivo il primo parser. Il progetto è descritto, con tutta la dovuta umiltà ingegneristica, come “Parser per file TMX, SDL/XLIFF e TXML e importatore senza vergogna in Mozilla Pontoon”. Quel “senza vergogna” sta facendo molto lavoro in quella frase.

🔍
Retrospettiva 2026
Colore è ancora vivo a github.com/ifad/coloreGeremia Taglialatela ha preso in mano il progetto dopo che io mi sono spostato su altre cose, e l’ha portato avanti attraverso Ruby 2.7, 3.0, 3.1, 3.2, sidekiq 6, e CI moderna. È a 354 commit — tre volte i miei. Il modulo C per nginx che Joe ha scritto a febbraio 2015 è invariato. Heathen come servizio standalone è stato alla fine assorbito direttamente dentro Colore come libreria; il repo originale è archiviato ma il codice vive dentro lib/heathen/ di Colore. Stessa idea, meno componenti.

L’IFAD è un’agenzia delle Nazioni Unite che gira sui documenti. Accordi di prestito, rapporti di valutazione, note strategiche per Paese, decisioni del Board, brief di progetto — ogni applicazione web che costruiamo prima o poi deve prendere un file Word e restituire un PDF, o prendere una scansione e restituire qualcosa di indicizzabile, o prendere un blob qualsiasi e farne una thumbnail. Tre anni fa abbiamo deciso di smettere di risolvere questo problema un’applicazione alla volta e di metterlo dietro un singolo servizio.

Oggi sto mergiando la v1.0.0 di Colore. È il secondo tentativo di quel servizio, ed è quello che ci teniamo. Questa è la storia di entrambi i tentativi e delle persone che li hanno costruiti — perché quasi nessuna riga del codice qui sotto è mia.

📜

Questo articolo è stato scritto nel 2015. È qui per ragioni storiche — i dettagli tecnici potrebbero non essere più validi.

🔍
Retrospettiva 2026
Eaco ha raggiunto la v1.0.0 il 5 maggio 2016 — messaggio di commit: “This is v1.0.0. Two years in production.” E’ cresciuto fino a 54 stelle, 8 fork, 240 commit, e ha gestito l’autorizzazione all’IFAD per altri cinque anni. Geremia Taglialatela l’ha preso in mano nel 2020 e l’ha mantenuto su Rails 6.0 e 6.1, poi ha modernizzato la CI a fine 2025. Il pattern ABAC con ACL-come-hash si e’ rivelato esattamente la scelta giusta per un’organizzazione dove l’accesso e’ determinato da posizione, dipartimento e gruppo di lavoro — non solo “admin o no.” Il repo e’ ancora online, e la documentazione YARD e’ ancora tra le piu’ complete che abbia mai scritto per una gem.

Scriptoria e’ un’applicazione interna di workflow all’IFAD — un’agenzia specializzata delle Nazioni Unite a Roma — e il suo layer di autorizzazione mi sta dando sui nervi da mesi. Il codice funziona, ma e’ aggrovigliato nell’app. Ogni volta che dobbiamo aggiungere un nuovo ruolo o cambiare chi puo’ accedere a cosa, stiamo editando codice applicativo che non dovrebbe occuparsi di semantica di autorizzazione.

Cosi’ otto giorni fa ho iniziato a estrarlo. Oggi rilascio il risultato: Eaco — un framework di Attribute-Based Access Control per Ruby, che prende il nome da Eaco, il guardiano delle chiavi dell’Ade nella mitologia greca.

172 commit. Cinque release. 100% di test coverage. E un sabato pomeriggio che non rivedro’ mai piu'.


In questa pagina