1 24/05/2026 10 min

Quando servono davvero i kernel headers

Su AlmaLinux 9 e Rocky Linux 9 i kernel headers non sono un dettaglio cosmetico: servono quando devi compilare moduli esterni rispetto al kernel, per esempio driver DKMS, agent di sicurezza, moduli per filesystem, software di virtualizzazione o componenti vendor che non arrivano già compilati per il tuo kernel.

Il punto pratico è semplice: i header devono corrispondere al kernel installato e, nella maggior parte dei casi, a quello in esecuzione. Se installi il pacchetto sbagliato, la compilazione può partire e poi fallire con errori del tipo missing /lib/modules/.../build, simboli non trovati o incompatibilità tra versioni.

Qui non stiamo parlando del kernel “generico” o del pacchetto sorgente completo del kernel. Su queste distribuzioni il caso normale è installare il pacchetto di sviluppo corretto dal repository di sistema, verificare che il repository richiesto sia abilitato e controllare che il filesystem esponga i collegamenti giusti sotto /lib/modules/$(uname -r)/.

Verifica iniziale: kernel in esecuzione e pacchetti disponibili

Prima di toccare il sistema, conviene raccogliere due informazioni: quale kernel è attivo e quali pacchetti sono già presenti. Questo evita di installare headers o development package che non combaciano con la macchina.

Esegui questi controlli:

uname -r
rpm -q kernel kernel-core kernel-devel kernel-headers
ls -l /lib/modules/$(uname -r)/build
ls -l /lib/modules/$(uname -r)/source

Interpretazione rapida:

  • se kernel-devel non è installato, di solito manca il materiale necessario per compilare moduli;
  • se /lib/modules/$(uname -r)/build non esiste o punta male, il pacchetto non è allineato al kernel corrente;
  • se hai appena aggiornato il sistema ma non hai riavviato, il kernel in esecuzione può essere più vecchio di quello per cui hai già i pacchetti installati.

Nota importante: su RHEL-like 9 la parola “headers” viene spesso usata in modo generico, ma nella pratica per compilare moduli il pacchetto davvero utile è quasi sempre kernel-devel. Il pacchetto kernel-headers serve a esporre header user-space per la compilazione di alcune componenti, ma non sostituisce il development tree del kernel per i moduli esterni.

Differenza tra kernel-headers e kernel-devel

Questo è il punto che genera più confusione. Su AlmaLinux 9 e Rocky Linux 9 i due pacchetti non sono equivalenti.

  • kernel-headers: espone header necessari a parte del software user-space che interagisce con il kernel o con le ABI del sistema.
  • kernel-devel: contiene i file per compilare moduli kernel e integrare software che deve agganciarsi al kernel in esecuzione.

Se il tuo obiettivo è installare headers per una compilazione classica di moduli, il comando giusto è quasi sempre quello che installa kernel-devel. Se invece stai seguendo un requisito specifico di un software che chiede esplicitamente kernel-headers, installa anche quello, ma non confondere il risultato con il development tree del kernel.

In altre parole: per compilare moduli esterni, kernel-devel è la base; kernel-headers è complementare. Se non distingui i due casi, rischi di avere un sistema che “sembra” preparato ma poi fallisce al primo build serio.

Installazione standard con dnf

La via più pulita è usare i repository standard della distribuzione. Se la macchina ha accesso a internet e i repo sono configurati correttamente, il flusso normale è questo:

sudo dnf install -y kernel-devel kernel-headers

Dopo l’installazione, verifica che il pacchetto kernel-devel corrisponda alla versione del kernel attivo o, se non hai ancora riavviato dopo un update, almeno alla versione che andrai a usare al prossimo boot:

rpm -q kernel-devel kernel-headers
rpm -qa 'kernel*' | sort

Il controllo più concreto resta il link di build:

readlink -f /lib/modules/$(uname -r)/build

Se il comando restituisce un path valido sotto /usr/src/kernels/, sei sulla strada giusta. Se invece il link non esiste, c’è un disallineamento da correggere prima di procedere con il software che dipende dai moduli.

Scenario tipico: il kernel è stato aggiornato ma il sistema non è stato riavviato

Questo è uno dei casi più comuni in produzione: il sistema ha già scaricato il nuovo kernel e magari anche il relativo kernel-devel, ma il nodo continua a girare sul kernel vecchio. In quel caso l’installazione “sembra” a posto, però la compilazione fallisce perché i file presenti non corrispondono al kernel attualmente in esecuzione.

Per capirlo, confronta la versione del kernel attivo con quella del pacchetto installato:

uname -r
rpm -q kernel-devel

Se le versioni non coincidono, hai due strade:

  1. riavviare la macchina nel kernel per cui hai i pacchetti corretti;
  2. installare il pacchetto kernel-devel che corrisponde esattamente al kernel in esecuzione, se disponibile nei repository.

In ambienti con finestre di manutenzione strette, il riavvio è spesso la soluzione più pulita. Se però il nodo è critico e devi evitare downtime, conviene verificare prima se il package matching è già presente e basta solo riallineare il boot successivo.

Repository mancanti, CRB e casi offline

Su AlmaLinux 9 e Rocky Linux 9 alcuni pacchetti richiesti da software di terze parti arrivano da repository aggiuntivi. In particolare può servire il repository CRB per dipendenze di build o librerie accessorie. Non sempre riguarda direttamente i headers del kernel, ma spesso il problema emerge nello stesso momento: installi i pacchetti di build, e la catena si ferma su una dipendenza mancante.

Controlla i repository attivi con:

sudo dnf repolist
sudo dnf config-manager --set-enabled crb

Se la macchina è offline o isolata, il criterio cambia: devi verificare che il mirror interno contenga i pacchetti corretti per la stessa release della macchina. In quel caso il controllo non è “installare e basta”, ma confrontare il contenuto del repository con la versione del sistema:

cat /etc/os-release
rpm -q --queryformat '%{VERSION}-%{RELEASE}\n' kernel-devel

Se il mirror non ha il pacchetto corretto, non forzare installazioni da sorgenti miste o da release diverse: il costo di un modulo compilato contro ABI sbagliate è quasi sempre più alto del tempo necessario a sistemare il repository.

Verifica pratica con un modulo esterno

Il modo migliore per confermare che gli headers siano davvero a posto è provare una compilazione reale. Se usi DKMS o un driver vendor, il loro log è la prova utile; in alternativa puoi osservare se il tool di build trova il tree del kernel senza errori.

Due controlli ricorrenti:

  1. il percorso /lib/modules/$(uname -r)/build esiste e punta al tree corretto;
  2. il comando di build non si ferma su errori di intestazione o simboli mancanti.

Se stai usando DKMS, il log più utile è spesso sotto /var/lib/dkms/. Un errore classico è il seguente: il modulo cerca l’albero di compilazione ma trova un kernel-devel non allineato o incompleto. In quel caso il messaggio è più affidabile del “pacchetto installato” visto da rpm.

sudo dkms status
sudo find /var/lib/dkms -maxdepth 3 -type f | sort
sudo journalctl -xe --no-pager | tail -n 50

Se il modulo compila ma poi non si carica, il problema non è più “headers mancanti”: devi guardare firma del modulo, Secure Boot, permessi o compatibilità del driver. Gli headers ti portano solo fino alla build, non risolvono il caricamento del modulo.

Installazione in ambienti con Secure Boot o policy restrittive

Su sistemi con Secure Boot attivo, il fatto che i kernel headers siano installati non significa che il modulo possa essere caricato. La compilazione può andare a buon fine, ma il kernel può rifiutare il modulo non firmato. È un errore di livello diverso, ma nelle operazioni di installazione viene spesso scambiato per “headers mancanti”.

La verifica minima è questa:

mokutil --sb-state
journalctl -k --no-pager | tail -n 50

Se il kernel rifiuta un modulo, nel log vedrai indicazioni esplicite su firma o policy. In quel caso la soluzione non è reinstallare i headers, ma gestire la firma del modulo, la registrazione della chiave MOK o la policy di boot aziendale. È una distinzione importante: evita di inseguire il livello sbagliato.

Procedura consigliata in ordine operativo

Se vuoi fare le cose senza tentativi casuali, il flusso più pulito è questo:

  1. verifica il kernel in esecuzione con uname -r;
  2. controlla se kernel-devel e kernel-headers sono installati con rpm -q kernel-devel kernel-headers;
  3. controlla il link /lib/modules/$(uname -r)/build;
  4. installa o riallinea i pacchetti con sudo dnf install -y kernel-devel kernel-headers;
  5. se il kernel è stato aggiornato e non hai riavviato, valuta il reboot controllato;
  6. rilancia la compilazione del modulo o del software che dipende dagli headers;
  7. se fallisce ancora, apri il log del tool specifico prima di cambiare altri pacchetti.

Questa sequenza riduce il rumore: prima fai corrispondere kernel e pacchetti, poi verifichi il build tree, infine guardi il log applicativo. Saltare direttamente alla reinstallazione è il modo più rapido per perdere tempo, soprattutto su host con repository misti o con aggiornamenti parziali.

Controlli finali dopo l’installazione

Dopo aver installato i pacchetti, i controlli che contano davvero sono tre: presenza del pacchetto giusto, link di build corretto, e compilazione reale senza errori. Tutto il resto è contorno.

rpm -q kernel-devel kernel-headers
readlink -f /lib/modules/$(uname -r)/build
ls -ld /usr/src/kernels/$(uname -r)*

Se il tuo software richiede un comando di test specifico, usalo subito. Per esempio, molti pacchetti DKMS espongono uno stato sintetico che è più utile del semplice elenco RPM. In alternativa, il successo del primo rebuild è la conferma più concreta che la macchina è pronta.

Se invece il sistema continua a fallire, non dare per scontato che il problema siano ancora gli headers. Le cause successive da verificare sono: repository non allineato, kernel vecchio in esecuzione, modulo non firmato, dipendenze di build mancanti, o path corrotti sotto /lib/modules.

Errori frequenti e come leggerli senza perdere tempo

Ci sono alcuni messaggi che si ripetono spesso e che conviene riconoscere subito.

  • file not found: /lib/modules/.../build — di solito manca kernel-devel o non coincide con il kernel attivo.
  • invalid module format — il modulo è stato compilato per un kernel diverso o con opzioni incompatibili.
  • permission denied / operation not permitted durante il caricamento — spesso non è un problema di headers, ma di policy, Secure Boot o permessi.
  • missing symbols — il development tree non è quello giusto, oppure il vendor richiede una specifica build del kernel.

Leggere bene il primo errore utile fa risparmiare tempo. Il kernel è molto esplicito quando qualcosa non combacia; il problema nasce quando si cerca di correggere il livello sbagliato. Se il log parla di firma, non reinstallare i headers. Se parla di build tree mancante, non inseguire il firewall. Se parla di symbol mismatch, non fermarti al pacchetto RPM installato.

Conclusione operativa: cosa ricordare su AlmaLinux 9 e Rocky Linux 9

La regola utile è questa: per compilare moduli esterni su AlmaLinux 9 e Rocky Linux 9, installa e allinea kernel-devel al kernel in esecuzione; aggiungi kernel-headers quando il software lo richiede esplicitamente. Non trattare i due pacchetti come sinonimi.

Se il sistema è aggiornato ma non riavviato, il mismatch è il primo sospetto. Se la macchina usa repository parziali o mirror interni, verifica che la release sia coerente. Se Secure Boot è attivo, separa il tema headers dal tema firma dei moduli. E se un driver o un agente continua a fallire dopo l’installazione, guarda il log del tool di build prima di cambiare altra configurazione.

In pratica: prima fai combaciare versione del kernel, pacchetti e tree di compilazione; poi risolvi il resto. È la differenza tra una correzione pulita e una serie di tentativi che spostano solo il problema da un layer all’altro.