Configurare un indirizzo IP statico su Debian e Ubuntu

Pubblicato il 13 min di lettura

Indirizzi IPv4 e IPv6 fissi su Ubuntu 24.04, Ubuntu 22.04, Debian 13 e Debian 12: netplan, ifupdown e systemd-networkd a confronto, con strategia di rollback e indirizzi IP aggiuntivi.

Quattro dati senza i quali non dovresti iniziare

Impostare un indirizzo statico richiede pochi minuti. Il motivo per cui tanti server restano comunque muti dopo il riavvio non è quasi mai la sintassi, ma il fatto che uno dei quattro dati di base sia stato indovinato invece che letto: nome dell'interfaccia, indirizzo con lunghezza del prefisso, gateway e nameserver. Leggi questi valori a sistema funzionante, finché la macchina è ancora raggiungibile.

ip -brief address show
ip -4 route show
ip -6 route show
cat /etc/resolv.conf

La prima riga restituisce il nome dell'interfaccia. Sui server virtuali, a seconda della piattaforma, si chiama ens3, enp1s0 o eth0, sul bare metal spesso eno1. Copia il nome, non tirare a indovinare. Un errore di battitura in questo punto produce una configurazione sintatticamente ineccepibile che semplicemente non corrisponde a nessuna scheda presente.

La lunghezza del prefisso merita un'attenzione particolare. Molti provider instradano un singolo indirizzo IPv4 con /32 verso il server e in quel caso il gateway si trova fuori dalla propria subnet. Altri assegnano classiche reti /24. Quale dei due casi si applica lo rivela il percorso realmente utilizzato:

ip route get 1.1.1.1

Subito dopo crea un backup. Costa dieci secondi ed è la differenza tra un rollback e un ticket.

cp -a /etc/netplan /root/netplan.bak
cp -a /etc/network/interfaces /root/interfaces.bak

Quale sistema gestisce la tua rete in questo momento?

Debian e Ubuntu usano strumenti diversi e il blackout totale più frequente nasce quando due di essi configurano la stessa scheda nello stesso momento. Per prima cosa fai chiarezza:

ls -l /etc/netplan/
ls -l /etc/network/interfaces /etc/network/interfaces.d/
ls -l /etc/systemd/network/

La regola pratica per le quattro versioni attuali: Ubuntu 24.04 e Ubuntu 22.04 si configurano tramite netplan, che dietro le quinte pilota systemd-networkd. Debian 13 e Debian 12, dopo un'installazione standard, arrivano con ifupdown e il file /etc/network/interfaces. Su Debian systemd-networkd è presente ma non attivo, e netplan si può installare a posteriori, anche se non è la strada prevista.

Sulle immagini cloud si aggiunge un ulteriore livello: al primo avvio cloud-init scrive un file proprio, di solito /etc/netplan/50-cloud-init.yaml oppure, su Debian, un blocco in /etc/network/interfaces.d/. Se modifichi quel file senza frenare cloud-init, dopo il riavvio successivo ti ritrovi davanti la vecchia configurazione.

Ubuntu 24.04 e 22.04: indirizzo statico con netplan

netplan legge tutti i file in /etc/netplan/ in ordine alfabetico e li traduce in configurazione per systemd-networkd. Non creare un secondo file con la stessa interfaccia: modifica quello esistente oppure disattiva il vecchio in modo pulito. Una configurazione completa con IPv4 e IPv6 si presenta così:

network:
  version: 2
  renderer: networkd
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: false
      accept-ra: false
      addresses:
        - 203.0.113.10/24
        - "2001:db8:1234::2/64"
      routes:
        - to: default
          via: 203.0.113.1
        - to: default
          via: "2001:db8:1234::1"
      nameservers:
        addresses: [9.9.9.9, 149.112.112.112, 2620:fe::fe]

Tre punti meritano una spiegazione a parte.

Primo: le rotte predefinite stanno sotto routes e non più sotto gateway4 o gateway6. Queste due chiavi sono deprecate da netplan 0.103. Su Ubuntu 22.04 e 24.04 funzionano ancora, ma accompagnano ogni comando con `gateway4` has been deprecated, use default routes instead. Chi scrive una configurazione nuova, scrive rotte.

Secondo: accept-ra: false disattiva la configurazione IPv6 automatica. Se la lasci attiva mentre assegni anche un indirizzo fisso, la scheda si ritrova con due indirizzi e due rotte predefinite, e a decidere quale vince è la metrica, non la tua intenzione.

Terzo: i permessi del file. Da netplan 0.106 ogni comando avvisa se il file YAML è leggibile da altri utenti: Permissions for /etc/netplan/01-static.yaml are too open. Netplan configuration should NOT be accessible by others. Non è un dettaglio estetico, perché in questi file finiscono anche chiavi WLAN e dati dei tunnel.

chmod 600 /etc/netplan/*.yaml

Quando il gateway si trova fuori dalla propria subnet

Con un indirizzo instradato singolarmente in /32 il kernel non conosce alcun percorso diretto verso il gateway e rifiuta la rotta. Nel journal compare Could not set route: Network is unreachable, mentre al tentativo manuale con ip route add la risposta è RTNETLINK answers: Network is unreachable. La soluzione si chiama on-link:

      addresses:
        - 203.0.113.10/32
      routes:
        - to: default
          via: 192.0.2.1
          on-link: true

Con IPv6 il caso particolare diventa la regola: molte reti indicano come gateway l'indirizzo link-local fe80::1. Poiché netplan associa sempre le rotte a un'interfaccia, basta via: "fe80::1" nel blocco della scheda interessata.

Mettere a tacere cloud-init

Se nella directory è presente un file 50-cloud-init.yaml, imposta anche un blocco, altrimenti al prossimo avvio il tuo lavoro viene sovrascritto:

echo 'network: {config: disabled}' > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg

netplan try: il comando che non ti chiude fuori

L'ordine è: verificare, provare, rendere definitivo. netplan generate traduce i file YAML senza attivare nulla e segnala subito gli errori di sintassi. Solo dopo arriva il test vero e proprio.

netplan generate
netplan try --timeout 120
netplan apply

netplan try applica la nuova configurazione e ripristina automaticamente la vecchia se non premi Invio entro il tempo previsto. Il valore predefinito è di 120 secondi. È esattamente il motivo per cui su un server remoto non si comincia mai con netplan apply: un errore di battitura nell'indirizzo del gateway chiude la sessione SSH e, senza una rete di sicurezza, la faccenda finisce in console oppure con una reinstallazione.

Non fidarti ciecamente del ripristino automatico. Sono documentati casi in cui netplan try, allo scadere del tempo, non ha ripristinato la connessione, in particolare modificando il file generato da cloud-init. Dopo un rollback controlla sempre che il file su disco sia davvero tornato allo stato precedente.

Per tutto ciò che netplan try non copre (e per Debian con ifupdown, dove questo comando non esiste affatto) si è dimostrata utile una seconda cintura di sicurezza: un job di ripristino che rimette in gioco il backup se non ti fai vivo in tempo.

nohup sh -c 'sleep 300; cp -a /root/netplan.bak/. /etc/netplan/; netplan apply' >/dev/null 2>&1 &

Annota il numero di processo che compare nell'output. Se tutto funziona, termina il job con kill. Se invece non riesci più a entrare, si ripara da solo in cinque minuti. Lavora inoltre dentro tmux o screen, così una sessione SSH che cade non si porta via anche il tuo editor nel bel mezzo della modifica.

Sui server root KVM resta come ultima istanza la console nell'area clienti, con cui raggiungi il sistema anche senza una rete funzionante. Sulle macchine dedicate la strada del ritorno è decisamente più laboriosa, quindi lì la procedura di sicurezza vale doppio.

Debian 13 e 12 con /etc/network/interfaces

Dopo un'installazione standard è ifupdown a gestire la rete. La configurazione è orientata alle righe e prevede blocchi separati per ogni famiglia di indirizzi:

auto lo
iface lo inet loopback

auto ens3
iface ens3 inet static
    address 203.0.113.10/24
    gateway 203.0.113.1

iface ens3 inet6 static
    address 2001:db8:1234::2/64
    gateway 2001:db8:1234::1
    accept_ra 0

La riga auto ens3 vale per entrambi i blocchi, una seconda riga auto non serve. Se il gateway si trova fuori dalla subnet, funziona la stessa idea vista con netplan, solo formulata a mano:

iface ens3 inet static
    address 203.0.113.10/32
    post-up ip route add 192.0.2.1 dev ens3
    post-up ip route add default via 192.0.2.1
    pre-down ip route del default via 192.0.2.1

L'insidia più grande su Debian non è la sintassi, ma l'attivazione. systemctl restart networking abbassa brevemente la scheda e, se la nuova configurazione non regge, la sessione sparisce. ifdown ens3 && ifup ens3 è ancora più delicato, perché ifup non viene mai eseguito se la connessione cade già durante ifdown. Prepara quindi prima il job di ripristino descritto sopra e poi lancia:

systemctl restart networking
systemctl status networking

Qui incontrerai regolarmente due messaggi. ifup: interface ens3 already configured significa che ifupdown considera ancora attiva la scheda, anche se magari non lo è più; lo stato è registrato in /run/network/ifstate. E Job for networking.service failed because the control process exited with error code è soltanto il guscio esterno: il motivo vero si trova in journalctl -xeu networking, di solito una rotta predefinita assegnata due volte con RTNETLINK answers: File exists.

DNS con ifupdown

La riga apparentemente ovvia dns-nameservers 9.9.9.9 nel file ha effetto solo se è installato un intermediario che la riporta in /etc/resolv.conf, classicamente il pacchetto resolvconf. Senza quell'intermediario la voce resta senza conseguenze, e te ne accorgi solo quando i nomi smettono di risolversi: Temporary failure in name resolution. Se preferisci non installare altro, gestisci /etc/resolv.conf direttamente e verifica con ls -l /etc/resolv.conf se il file è un symlink, cioè se è gestito da un altro servizio.

Usare systemd-networkd su Debian

Se su un server Debian usi comunque gli strumenti systemd oppure gestisci molte interfacce e tunnel, con systemd-networkd ottieni un impianto più coerente. Il passaggio si compone di tre fasi: creare la configurazione, attivare il nuovo servizio, mettere a riposo il vecchio.

[Match]
Name=ens3

[Network]
Address=203.0.113.10/24
Address=2001:db8:1234::2/64
Gateway=203.0.113.1
Gateway=2001:db8:1234::1
DNS=9.9.9.9
DNS=2620:fe::fe
IPv6AcceptRA=no

Questo file va in /etc/systemd/network/10-ens3.network. Per un gateway fuori dalla subnet aggiungi un blocco di rotta dedicato:

[Route]
Gateway=192.0.2.1
GatewayOnLink=yes

Poi il passaggio vero e proprio, meglio ancora una volta con il job di ripristino alle spalle:

systemctl enable --now systemd-networkd
systemctl disable networking
networkctl status ens3

L'output di networkctl status è il riscontro più onesto che questo argomento possa offrire. Se leggi State: routable (configured), il servizio ha accettato il file e lo ha applicato. Se invece leggi configuring oppure degraded, ci ha provato e ha fallito, a prescindere dal fatto che il comando di avvio sia tornato senza errori.

Su Debian la parte DNS è a sé stante: systemd-networkd inserisce i nameserver nella risoluzione solo se systemd-resolved è in esecuzione e /etc/resolv.conf punta al suo file.

apt-cache policy systemd-resolved

Questa interrogazione dipende dalla versione e inganna in modo poco appariscente. Un pacchetto autonomo systemd-resolved esiste solo a partire da Debian 12 e Ubuntu 24.04, e lì il comando riporta un numero di versione. Su Ubuntu 22.04 il servizio è invece ancora dentro il pacchetto systemd, quindi il comando termina senza errori ma non stampa assolutamente nulla. Un'installazione fallisce di conseguenza con Unable to locate package systemd-resolved. L'output vuoto non significa quindi che manchi il resolver, ma che su questa versione il pacchetto non esiste. Su sistemi più vecchi come Debian 11 il comportamento è identico. Su queste versioni controlla invece:

apt-cache policy systemd
systemctl status systemd-resolved

Il servizio si attiva con systemctl enable --now systemd-resolved, dopodiché il consueto symlink punta a /run/systemd/resolve/stub-resolv.conf. Se non vuoi questa strada, rinuncia a systemd-resolved e scrivi i nameserver in modo statico in /etc/resolv.conf. Quello che invece non dovresti fare: entrambe le cose a metà.

Aggiungere indirizzi IP supplementari

Gli indirizzi aggiuntivi non sono un caso particolare, sono semplicemente una voce in più. Con netplan la lista cresce:

      addresses:
        - 203.0.113.10/24
        - 203.0.113.11/24
        - 203.0.113.12/24
        - "2001:db8:1234::2/64"
        - "2001:db8:1234::3/64"

Con systemd-networkd scrivi più righe Address= una sotto l'altra. Con ifupdown integri la definizione esistente invece di crearne una seconda:

iface ens3 inet static
    address 203.0.113.10/24
    gateway 203.0.113.1
    post-up ip addr add 203.0.113.11/24 dev ens3
    post-up ip addr add 203.0.113.12/24 dev ens3
    pre-down ip addr del 203.0.113.11/24 dev ens3
    pre-down ip addr del 203.0.113.12/24 dev ens3

La vecchia notazione con ens3:0 funziona ancora, ma è un reperto dell'epoca precedente allo strumento ip. Non crea veri dispositivi aggiuntivi, solo etichette, e nelle regole firewall genera più confusione di quanta utilità porti.

Con gli indirizzi aggiuntivi tre cose vanno storte tipicamente. Primo: l'indirizzo non è assegnato lato server; nessuna configurazione di sistema operativo al mondo fa funzionare un IP che non è instradato verso il tuo server, quindi il controllo nell'area clienti è il primo passo e non l'ultimo. Secondo: a un secondo indirizzo della stessa rete non spetta una seconda rotta predefinita; una seconda voce di gateway di default ti regala RTNETLINK answers: File exists oppure, peggio ancora, percorsi di risposta che cambiano. Terzo: con IPv6 vale quasi sempre che l'intero /64 è instradato verso il server, quindi puoi scegliere liberamente all'interno dell'intervallo, ma come indirizzo di interfaccia configurato serve davvero solo quello indicato dal provider.

Se un indirizzo aggiuntivo funziona davvero verso l'esterno lo verifichi in modo mirato passando dal punto di origine:

ping -c 3 -I 203.0.113.11 1.1.1.1

Come capisci che tutto è davvero a posto

Il fatto che un comando sia terminato senza messaggi di errore dice poco sullo stato della rete. Questi cinque controlli invece dicono qualcosa:

  1. L'indirizzo è sulla scheda giusta: ip -brief address show mostra esattamente gli indirizzi voluti e nessun residuo della vecchia configurazione.
  2. Il percorso verso l'esterno è corretto, indirizzo di origine compreso: ip route get 1.1.1.1 riporta il gateway atteso e il src atteso.
  3. IPv6 ha una rotta predefinita propria: ip -6 route show default non deve restare vuoto, altrimenti tutto passa silenziosamente da IPv4.
  4. La risoluzione dei nomi funziona indipendentemente dalla raggiungibilità: getent hosts deb.debian.org restituisce un indirizzo e non soltanto silenzio.
  5. L'unico test davvero valido è un riavvio. Solo dopo sai se la configurazione arriva dal file oppure ancora dalla RAM.

Su Ubuntu netplan status --all fornisce in più un riepilogo compatto, con systemd-networkd fa lo stesso networkctl status. Nel dubbio, entrambi mostrano che un indirizzo è sì presente nel file, ma non è mai stato applicato.

I messaggi di errore, alla lettera

MessaggioCausa e rimedio
Invalid YAML at /etc/netplan/01-static.yaml line 6 column 8: did not find expected keyTabulazione al posto degli spazi oppure indentazione fuori posto. YAML non ammette tabulazioni: usa due spazi per livello.
Error in network definition: unknown key 'gateway'In netplan la chiave non si chiama gateway. Scrivi una voce sotto routes con to: default.
`gateway4` has been deprecated, use default routes insteadSolo un avviso, la configurazione è ancora valida. Conviene comunque passare a routes.
Permissions for /etc/netplan/… are too openApplica chmod 600 al file YAML.
RTNETLINK answers: Network is unreachableIl gateway si trova fuori dalla subnet configurata. Imposta on-link: true oppure GatewayOnLink=yes, o correggi la lunghezza del prefisso.
RTNETLINK answers: File existsL'indirizzo o la rotta esistono già, di solito perché due sistemi di configurazione lavorano contemporaneamente.
Error: Cannot find device "eth0"La scheda ha un altro nome. Leggilo con ip -brief link show.
Temporary failure in name resolutionIl routing regge, il DNS no. Controlla /etc/resolv.conf e chiarisci quale servizio scrive questo file.
ifup: interface ens3 already configuredifupdown considera attiva la scheda. Verifica lo stato in /run/network/ifstate.

Le quattro distribuzioni a confronto diretto

Debian 12Debian 13Ubuntu 22.04Ubuntu 24.04
Strumento predefinitoifupdownifupdownnetplannetplan
File principale/etc/network/interfaces/etc/network/interfaces/etc/netplan/*.yaml/etc/netplan/*.yaml
Alternativasystemd-networkdsystemd-networkdsystemd-networkd direttosystemd-networkd diretto
Test senza chiudersi fuorijob di ripristino propriojob di ripristino proprionetplan trynetplan try
systemd-resolvedpacchetto a sé, inattivopacchetto a sé, inattivoparte di systemdpacchetto a sé, attivo
Avviso sui permessi netplannon pertinentenon pertinenteda 0.106

Se subito dopo la configurazione di rete metti in funzione il firewall, fai attenzione al fatto che le regole per il nuovo indirizzo e quelle per IPv6 valgono separatamente. Come impostare il tutto in modo pulito lo trovi nella nostra guida a UFW su Debian e Ubuntu, e come proteggere l'accesso subito dopo in Mettere in sicurezza il server SSH.

Riepilogo per il prossimo server

Leggere i valori invece di indovinarli, creare un backup, scrivere la configurazione, provarla con netplan try o con un job di ripristino proprio, renderla definitiva, riavviare e solo allora considerare chiusa la faccenda. Chi rispetta questa sequenza perde nel peggiore dei casi cinque minuti. Chi la accorcia perde nel peggiore dei casi il server, finché qualcuno non si siede alla console.

Domande frequenti

Perché il mio server non è più raggiungibile dopo netplan apply?
Quasi sempre il gateway è sbagliato oppure la lunghezza del prefisso non corrisponde alla rete. Per questo sui sistemi remoti conviene usare prima netplan try, che ripristina automaticamente la configurazione precedente dopo 120 secondi se nessuno preme Invio. Se il danno è già fatto, sui server root KVM ti salva la console nell'area clienti.
Debian 13 usa netplan?
No. Dopo un'installazione standard, Debian 13 continua a configurare la rete tramite ifupdown e /etc/network/interfaces. netplan si può installare dai repository dei pacchetti, ma su Debian non è la strada prevista e aggiunge un ulteriore passaggio di traduzione. Come alternativa più vicina al sistema resta systemd-networkd.
Che cosa sostituisce gateway4 in netplan?
Una voce sotto routes con to: default e via: indirizzo del gateway. gateway4 e gateway6 sono deprecati da netplan 0.103 e generano l'avviso che al loro posto vanno usate le rotte predefinite. Su Ubuntu 22.04 e 24.04 le vecchie chiavi funzionano ancora, ma andrebbero sostituite a ogni revisione della configurazione.
Perché il mio /etc/resolv.conf viene sovrascritto di continuo?
Perché lo gestisce un servizio: systemd-resolved, resolvconf oppure cloud-init. Verifica con ls -l /etc/resolv.conf se il file è un symlink. O si inseriscono i nameserver dove il rispettivo servizio se li aspetta, oppure si disattiva il servizio e si gestisce il file in modo statico. Fare entrambe le cose a metà porta a disservizi dopo il riavvio.
Come aggiungo un indirizzo IP supplementare?
Con netplan come ulteriore voce nella lista addresses, con systemd-networkd come riga Address= aggiuntiva, con ifupdown tramite post-up ip addr add. L'importante è che non nasca una seconda rotta predefinita e che l'indirizzo sia davvero instradato verso il server. Questo si controlla nell'area clienti, prima di mettersi a cercare nel sistema operativo.
Il mio gateway è fuori dalla subnet, che cosa faccio?
È la norma con gli indirizzi instradati singolarmente in /32. In netplan si imposta on-link: true sulla rotta predefinita, con systemd-networkd GatewayOnLink=yes nel blocco della rotta, con ifupdown si crea prima una rotta host verso il gateway tramite post-up. Senza questo passaggio il kernel segnala Network is unreachable.

Debian Ubuntu netplan systemd-networkd Rete IPv6 Amministrazione Linux Server root