Aggiornare un server Linux in sicurezza con apt
La differenza fra upgrade, full-upgrade e dist-upgrade, i pacchetti trattenuti, le domande di configurazione di dpkg, il riavvio del kernel con needrestart e il passaggio di versione come categoria a sé.
Su un server appena installato un upgrade è una formalità: non c'è nulla che possa rompersi. Non appena il server ospita dei servizi, sono i dettagli a decidere se l'upgrade passa inosservato oppure se al termine un file di configurazione è stato sovrascritto, un servizio tiene ancora in memoria la vecchia libreria o il kernel in esecuzione è diverso da quello presente sul disco. Questo articolo li affronta uno per uno. La versione breve per un sistema appena messo in produzione si trova nella checklist per un nuovo server root.
Tutte le indicazioni si riferiscono a Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS e Ubuntu 22.04 LTS. I comandi sono scritti per l'esecuzione come root. Se lavori come utente normale, anteponi sudo a ogni comando.
Prima di lanciare il primo comando: la via di ritorno
Un upgrade può costare caro in tre modi: una domanda di configurazione sovrascrive la configurazione SSH, un nuovo kernel non si avvia, oppure la connessione cade nel bel mezzo di una transazione dpkg. Tutti e tre i casi sono gestibili, ma solo se prendi le tue precauzioni in anticipo.
Una sessione che sopravvive alla caduta della connessione
Se la connessione SSH cade durante lo scompattamento, il processo in esecuzione riceve un SIGHUP e dpkg si ferma a metà transazione. Il risultato è un database dei pacchetti configurato solo a metà. Esegui quindi gli upgrade più lunghi in una sessione che continua a girare sul server anche quando il tuo terminale sparisce:
apt install -y tmux
tmux new -s upgrade
Se la connessione salta, accedi di nuovo e riprendi la sessione con tmux attach -t upgrade. Nel frattempo l'operazione è proseguita.
La via d'accesso al server quando SSH non risponde più
Sui server root KVM e sui server dedicati di KernelHost raggiungi la console VNC dall'area clienti. Non dipende dallo stack di rete del sistema ospite e funziona anche quando nessun servizio è più in ascolto. Accedi almeno una volta per quella strada prima di iniziare e assicurati di conoscere la password di root.
Per il caso di un kernel che non si avvia ti serve inoltre un menu di avvio visibile. Sui server è spesso nascosto:
grep -E '^GRUB_TIMEOUT|^GRUB_TIMEOUT_STYLE' /etc/default/grub
Se lì compaiono GRUB_TIMEOUT_STYLE=hidden oppure GRUB_TIMEOUT=0, imposta GRUB_TIMEOUT_STYLE=menu e GRUB_TIMEOUT=5 e lancia update-grub. In caso di emergenza scegli nella console VNC, sotto "Advanced options", il kernel precedente.
Verificare lo stato e metterlo per iscritto
Tre verifiche preliminari che trovano qualcosa più spesso di quanto ci si aspetti:
df -h / /boot /var
dpkg --audit
apt-get check
Controllo di riuscita: dpkg --audit non stampa nulla, apt-get check arriva in fondo senza righe di errore e in /boot restano liberi almeno 300 MB. Un /boot pieno è la causa più frequente di un upgrade del kernel interrotto, ne trovi di più in Disco pieno su Linux. Se dpkg --audit segnala qualcosa, riparalo prima con dpkg --configure -a.
Poi metti per iscritto lo stato attuale, così più tardi potrai confrontare:
dpkg --get-selections > /root/pacchetti-prima-upgrade.txt
apt-mark showhold > /root/holds-prima-upgrade.txt
cp -a /etc/apt /root/apt-config-$(date +%F)
update, upgrade, full-upgrade e dist-upgrade
Queste quattro parole vengono confuse di continuo. La differenza non è estetica: decide se viene installato un nuovo kernel e se i pacchetti possono sparire.
| Comando | Nuovi pacchetti | Rimuove pacchetti | Impiego |
|---|---|---|---|
apt update | no | no | scarica soltanto gli elenchi dei pacchetti, non tocca il sistema |
apt-get upgrade | no | no | la variante più prudente, trattiene gli update del kernel |
apt upgrade | sì, se una dipendenza lo richiede | no | il caso normale sui sistemi in produzione |
apt full-upgrade | sì | sì, se necessario | quando accetti consapevolmente delle rimozioni |
apt-get dist-upgrade | sì | sì, se necessario | il nome più vecchio per la stessa cosa |
Da qui derivano due conclusioni. Primo: dist-upgrade non ha nulla a che vedere con il passaggio a una nuova versione della distribuzione. Il nome è storico, il comando resta all'interno della tua versione attuale.
Secondo, la differenza fra apt upgrade e apt-get upgrade è esattamente il motivo per cui certi server restano senza un kernel nuovo. Debian integra il kernel tramite il metapacchetto linux-image-amd64, Ubuntu tramite linux-image-generic oppure linux-image-virtual. A ogni cambio di ABI questo metapacchetto punta a un pacchetto nuovo, il cui numero di versione compare nel nome. apt-get upgrade per principio non installa pacchetti nuovi e quindi lascia il kernel dov'è, mentre apt upgrade lo installa perché una dipendenza lo richiede. Chi usa apt-get upgrade in uno script di manutenzione ha bisogno lì anche di --with-new-pkgs.
Sulla scelta dello strumento: richiamato da uno script, apt stampa la riga WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Non è un messaggio di errore, ma un avviso legittimo. Negli script e nei ruoli Ansible va usato apt-get, in modalità interattiva apt è più comodo.
La procedura con una verifica dopo ogni passo
Passo 1: scaricare gli elenchi dei pacchetti.
apt update
Controllo di riuscita: l'output non contiene righe che iniziano con Err: oppure W:. Alla fine compare All packages are up to date. oppure un numero seguito da packages can be upgraded. Ogni riga di errore a questo punto significa che andresti avanti con un quadro incompleto.
Passo 2: guardare che cosa arriverebbe. Questo passo manca nella maggior parte delle guide ed è il più importante di tutta la procedura.
apt list --upgradable
apt full-upgrade -s
L'opzione -s simula e non modifica nulla. Le righe sotto The following packages will be REMOVED: sono le uniche che devi davvero controllare. Se lì non compare niente, full-upgrade è innocuo esattamente quanto upgrade. Se invece compare un pacchetto che ti serve, usa apt upgrade e chiarisci la causa separatamente.
Su Debian vale la pena aggiungere anche apt install apt-listchanges. Il pacchetto mostra prima dell'installazione i changelog e, cosa più importante, i file NEWS dei manutentori. Lì è scritto esattamente ciò che richiede lavoro manuale.
Passo 3: installare.
apt upgrade
Resta davanti allo schermo. L'operazione pone delle domande e un -y risponde soltanto a quella di apt, non alle richieste sui file di configurazione. Quelle arrivano da dpkg e aspettano con pazienza che qualcuno risponda.
Controllo di riuscita:
apt list --upgradable
dpkg --audit
systemctl --failed
journalctl -p 3 -b --no-pager | tail -n 20
Ci si aspetta questo: apt list --upgradable non stampa nulla oltre a Listing..., dpkg --audit tace, systemctl --failed segnala 0 loaded units listed. Quello che è successo davvero resta scritto in modo permanente in /var/log/apt/history.log, l'output completo di dpkg in /var/log/apt/term.log.
Pacchetti trattenuti: due cause diverse
Quando apt salta dei pacchetti, dietro ci sono due motivi radicalmente diversi che vengono regolarmente confusi.
Primo, un blocco vero e proprio. Qualcuno ha inchiodato il pacchetto in modo esplicito:
apt-mark showhold
Se il comando stampa qualcosa, si è trattato di una decisione consapevole, di solito su database o moduli del kernel. Lo togli con apt-mark unhold NOME_DEL_PACCHETTO, lo imposti con apt-mark hold NOME_DEL_PACCHETTO. Un blocco a livello di dpkg lo vedi con dpkg --get-selections | grep -w hold.
Secondo, il messaggio The following packages have been kept back:. Questo non è un blocco. Significa che per quell'upgrade apt dovrebbe installare un pacchetto in più oppure rimuoverne uno, e il comando usato non ha il permesso di farlo. La prova in una riga, senza modificare nulla:
apt full-upgrade -s | head -n 20
Se il pacchetto compare lì, la spiegazione è trovata e apt full-upgrade la risolve. Su Debian 13 la nuova generazione di apt formatta questo output in modo diverso, ma nella sostanza non cambia nulla.
Il caso particolare di Ubuntu. Ubuntu distribuisce gli aggiornamenti in modo scaglionato, non tutti i server li ricevono lo stesso giorno. Un pacchetto può quindi restare trattenuto anche se non esiste alcun blocco e nessuna dipendenza è di mezzo. La diagnosi procede per esclusione: apt-mark showhold è vuoto, apt full-upgrade -s non mostra alcuna rimozione e apt-cache policy NOME_DEL_PACCHETTO indica comunque un candidato più recente. In quel caso aspetta qualche giorno, oppure anticipa l'aggiornamento:
apt -o APT::Get::Always-Include-Phased-Updates=true upgrade
Su Debian 13 e Debian 12 la distribuzione scaglionata non esiste, quindi questa causa decade già in partenza.
Quando apt chiede che fare di un file di configurazione
Questa domanda compare solo quando ricorrono due condizioni insieme: il file è stato modificato localmente dopo l'installazione e il pacchetto porta con sé una nuova versione. Si presenta così:
Configuration file '/etc/ssh/sshd_config'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?
L'impostazione predefinita è N, cioè mantenere la tua versione. È la risposta sicura, ma non in ogni caso quella giusta.
| Situazione | Risposta |
|---|---|
| Non ricordi più che cosa era stato modificato | D, guardare la differenza e decidere dopo |
| Le tue modifiche sono volute, il pacchetto cambia solo dei commenti | N, poi confrontare il file .dpkg-dist |
| Il file proviene da uno strumento come cloud-init o Ansible | N, poi far girare di nuovo lo strumento |
| I nuovi valori predefiniti riguardano la sicurezza, la tua modifica è superflua | Y, poi rimettere le tue personalizzazioni |
| File critico e non sei sicuro | Z, copiare via il file, uscire dalla shell, poi N |
Con /etc/ssh/sshd_config serve una prudenza particolare: una Y può riportare PermitRootLogin e PasswordAuthentication ai valori del pacchetto, e proprio da quelli dipende il tuo accesso. Per questo le impostazioni SSH personali vanno in un file separato sotto /etc/ssh/sshd_config.d/, come descritto in Proteggere SSH e configurare l'accesso con chiave. Un file che nel pacchetto non esiste affatto non provoca mai una domanda.
Qualunque risposta tu dia, dpkg non butta via nulla. Con N la nuova versione finisce accanto come .dpkg-dist, con Y la tua vecchia come .dpkg-old. Passare in rassegna questi file è il vero lavoro successivo:
find /etc -name '*.dpkg-dist' -o -name '*.dpkg-old' -o -name '*.dpkg-new' -o -name '*.ucf-dist'
diff -u /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-dist
Per le esecuzioni non presidiate, per esempio dentro uno script di manutenzione, stabilisci il comportamento in anticipo. Questa combinazione mantiene la tua versione e non fa domande:
DEBIAN_FRONTEND=noninteractive apt-get -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
upgrade
--force-confnew sarebbe l'opposto e prende sempre la versione del pacchetto. Su un server con una configurazione personalizzata è raramente quello che vuoi.
Update del kernel e la questione del riavvio
Un nuovo kernel, al momento dell'installazione, finisce in /boot e nel menu di avvio. Il kernel in esecuzione resta invariato in memoria fino al riavvio. Un server può quindi essere allo stesso tempo aggiornato e vulnerabile. La prova più semplice è un confronto:
uname -r
ls -1 /boot/vmlinuz-*
Se in /boot c'è una versione più alta di quella che segnala uname -r, il riavvio è dovuto. Su Ubuntu 24.04 e 22.04 esiste in più un file segnalatore che tiene conto anche degli update delle librerie:
test -f /var/run/reboot-required && cat /var/run/reboot-required.pkgs
Il secondo file elenca i pacchetti che hanno richiesto il riavvio. Su Debian 13 e Debian 12 questo segnalatore non viene creato in modo affidabile, lì la strada giusta è needrestart.
needrestart: quali servizi usano ancora la vecchia libreria
Un update di OpenSSL o di glibc sostituisce il file sul disco. Ogni processo che lo ha già caricato continua a lavorare con la vecchia versione. needrestart individua esattamente questi processi. Su Ubuntu 24.04 e 22.04 è preinstallato e si fa vivo dopo ogni upgrade con una domanda a schermo intero, su Debian lo installi tu:
apt install -y needrestart
needrestart -b
La modalità -b produce un output leggibile da una macchina. Due indicazioni sono decisive: NEEDRESTART-KSTA con valore 1 significa che il kernel in esecuzione è quello atteso, qualsiasi altro valore significa che ce n'è pronto uno più recente. Ogni riga NEEDRESTART-SVC nomina un servizio che andrebbe riavviato.
Il comportamento lo governi con la variabile d'ambiente NEEDRESTART_MODE: a riavvia i servizi in automatico, l si limita a elencarli, i chiede conferma. In modo permanente vale lo stesso in /etc/needrestart/needrestart.conf. Per gli script la variabile è la scelta migliore, perché non modifica nulla nella configurazione:
NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
C'è un limite che conviene conoscere: needrestart guarda i processi del sistema host. I servizi nei container non li rinnova, lì ti servono immagini nuove.
Il passaggio di versione è una categoria a sé
Il passaggio da Debian 12 a Debian 13 oppure da Ubuntu 22.04 a 24.04 non è un upgrade nel senso visto sopra. Sostituisce le fonti dei pacchetti e rimpiazza praticamente ogni pacchetto. Tre regole valgono sempre: una versione per volta, nessuna versione intermedia saltata e, prima di iniziare, un backup da cui il server si possa ripristinare.
Su Debian converti per prima cosa le fonti. Debian 12 usa a questo scopo /etc/apt/sources.list, Debian 13 il file /etc/apt/sources.list.d/debian.sources nel formato più recente. Segue poi una procedura volutamente in due fasi, così come la prescrivono le note di rilascio:
apt update
apt-get upgrade --without-new-pkgs
apt full-upgrade
Il passo intermedio aggiorna per primi i pacchetti che se la cavano senza ristrutturazioni. Questo tiene basso il numero di pacchetti mossi contemporaneamente e rende riparabile un'interruzione. Non dimenticare il componente non-free-firmware: da Debian 12 è indipendente e manca nei vecchi file delle fonti. Se il tuo apt conosce il comando apt modernize-sources (lo verifichi con apt --version), converte il vecchio file delle fonti nel nuovo formato.
Su Ubuntu esiste uno strumento apposito e dovresti usare esclusivamente quello:
apt install -y ubuntu-release-upgrader-core
do-release-upgrade -c
do-release-upgrade
L'opzione -c si limita a controllare e non cambia nulla. Se il passaggio venga offerto dipende da Prompt in /etc/update-manager/release-upgrades: con lts compare solo il salto alla LTS successiva, e per giunta soltanto dopo la sua prima release intermedia. La strada da 20.04 a 24.04 passa obbligatoriamente per 22.04.
Un dettaglio che sorprende in molti: se do-release-upgrade gira via SSH, avvia un secondo servizio SSH sulla porta 1022 come ripiego e avvisa che quella porta potrebbe dover essere aperta nel firewall. Sfruttalo, ma non fidartene. La sessione tmux e l'accesso tramite la console VNC sono più affidabili.
Fare pulizia dopo l'upgrade
Dopo un giro corposo restano in giro tre tipi di residui: file di pacchetto scaricati, pacchetti orfani e resti di configurazione di pacchetti rimossi.
apt autoremove --purge
apt autoclean
autoclean cancella da /var/cache/apt/archives soltanto i file che comunque non vengono più offerti. apt clean svuota del tutto la cache, quindi libera più spazio, ma in cambio trasforma ogni nuova installazione in un download da zero.
I resti di configurazione li riconosci dallo stato dpkg rc, cioè rimosso ma con la configurazione ancora presente:
dpkg -l | awk '/^rc/ {print $2}'
Quello che compare lì lo elimini definitivamente con apt purge NOME_DEL_PACCHETTO. Con i vecchi kernel serve più attenzione, perché un errore rende il server non avviabile:
uname -r
dpkg -l 'linux-image-*' | awk '/^ii/ {print $2}'
Non rimuovere mai il kernel indicato dalla prima riga e tieni in più uno più vecchio ma funzionante, così il menu di avvio ha un ripiego. Nella maggior parte dei casi apt autoremove --purge se ne occupa comunque correttamente.
Errori frequenti e soluzioni
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr): è già in corso una seconda operazione sui pacchetti, di solito l'aggiornamento di sicurezza automatico. Non interromperla, lasciala arrivare in fondo. La procedura completa, riparazione inclusa, si trova in Risolvere l'errore apt Could not get lock.
E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem.: un'esecuzione precedente è stata interrotta, tipicamente da una caduta della connessione. Esegui esattamente quel comando e ripeti poi l'upgrade.
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).: un pacchetto è installato ma le sue dipendenze mancano. apt --fix-broken install le recupera. Se l'errore si ripresenta, quasi sempre la colpa è di una fonte esterna che offre pacchetti per un'altra versione della distribuzione.
E: Release file for http://deb.debian.org/debian/dists/trixie/InRelease is not valid yet (invalid for another 5h 3min 2s).: l'orologio del server è indietro. Verifica con timedatectl status se viene segnalato System clock synchronized: yes, correggi l'ora e ripeti apt update. Il repository non c'entra.
W: GPG error: ... The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ..., seguito da E: The repository '...' is not signed.: manca la chiave di firma di una fonte esterna, oppure è stata sostituita. Oggi la chiave va in /etc/apt/keyrings/ e viene richiamata nella riga della fonte tramite signed-by oppure tramite il campo Signed-By:. apt-key è deprecato e non andrebbe più usato.
E: Repository '... InRelease' changed its 'Suite' value from 'stable' to 'oldstable': succede normalmente quando esce una nuova versione di Debian e le tue fonti puntano a stable invece che al nome in codice. Conferma una volta con apt update --allow-releaseinfo-change, poi porta le fonti sul nome in codice. Un server che segue stable, altrimenti, prima o poi cambia versione della distribuzione senza volerlo.
E: The repository 'http://... Release' does not have a Release file.: la fonte non offre nulla per la tua versione, di solito perché una fonte esterna non supporta ancora quel nome in codice oppure perché la distribuzione ha raggiunto la fine del ciclo di vita. Disattiva la riga interessata e verifica la fonte.
No space left on device nel bel mezzo dello scompattamento: /boot oppure /var sono pieni. Fai ordine con dpkg --configure -a, libera spazio e riprova. Prima di ogni upgrade del kernel vale la pena dare un'occhiata a df -h /boot.
debconf: unable to initialize frontend: Dialog: soltanto un avviso, non un guasto. Compare in assenza di un terminale completo, per esempio dentro uno script. Con DEBIAN_FRONTEND=noninteractive sparisce.
I quattro sistemi a confronto
| Argomento | Debian 13 | Debian 12 | Ubuntu 24.04 | Ubuntu 22.04 |
|---|---|---|---|---|
| File delle fonti | sources.list.d/debian.sources | sources.list | sources.list.d/ubuntu.sources | sources.list |
| needrestart | da installare a parte | da installare a parte | preinstallato | preinstallato |
| Segnalatore di riavvio | inaffidabile, usare needrestart | inaffidabile, usare needrestart | /var/run/reboot-required | /var/run/reboot-required |
| Distribuzione scaglionata | no | no | sì | sì |
| Passaggio di versione | convertire le fonti, poi in due fasi | do-release-upgrade | ||
Il controllo finale
Il fatto che un comando sia tornato senza errori non significa che il sistema sia a posto. Queste sei verifiche dicono davvero qualcosa:
apt list --upgradablenon stampa nulla oltre aListing....apt-mark showholdcontiene solo ciò che hai bloccato consapevolmente.dpkg --audittace.needrestart -bsegnalaNEEDRESTART-KSTA: 1e nessun servizio in sospeso.systemctl --failednon elenca nulla.find /etc -name '*.dpkg-dist'non trova più niente, perché hai smaltito ogni differenza.
Se il punto quattro richiede un riavvio, pianificalo ed eseguilo. Un server che aspetta per mesi un riavvio in sospeso raccoglie esattamente le falle contro cui avevi aggiornato. Verifica poi un'ultima volta uname -r e systemctl --failed. Il riavvio è il momento in cui si vede se tutto risale davvero.
Domande frequenti
Qual è la differenza fra apt upgrade e apt full-upgrade?
dist-upgrade significa passare alla versione successiva della distribuzione?
Perché apt segnala "The following packages have been kept back"?
apt mi chiede se deve sostituire un file di configurazione. Che cosa devo rispondere?
Da che cosa capisco che dopo un upgrade serve un riavvio?
A che cosa mi serve needrestart, se tanto riavvio comunque?
Come aggiorno senza sorveglianza, evitando che l'esecuzione resti bloccata su una domanda?
Un upgrade può chiudermi fuori dal mio stesso server?
2026 KernelHost GmbH. Tutti i diritti riservati. Questa guida è protetta dal diritto d'autore. La ripubblicazione su altri siti web, anche parziale o in forma modificata, non è consentita senza il nostro consenso scritto. Le citazioni con indicazione della fonte e un link sono le benvenute.

