Installare Certbot per Apache su Ubuntu 24.04
Installa un certificato Let's Encrypt con un solo comando: Ubuntu 24.04 include Certbot 2.9.0 via apt. Evita l'errore ServerName che blocca l'emissione.
Cosa stai configurando
Un sito Apache su Ubuntu 24.04 raggiungibile tramite HTTPS, con un certificato Let's Encrypt gratuito e riconosciuto dai browser, emesso da Certbot e rinnovato automaticamente da un timer systemd a cui non dovrai più prestare attenzione. Il comando che esegue l'operazione è una sola riga. Tutti gli errori si verificano prima di quella riga: un vhost senza ServerName, la porta 80 bloccata dal firewall del provider, il DNS ancora configurato per puntare al vecchio server. Per questo motivo, la maggior parte della guida è dedicata ai prerequisiti e riporta la stringa di errore esatta generata da ogni errore di configurazione.
Due precisazioni sull'ambito. Se il tuo web server è nginx, il flusso è simile, ma il plugin e le configurazioni sono diversi: usa invece la versione di questa guida per nginx. Se il servizio da proteggere è accessibile soltanto internamente, ad esempio un pannello di amministrazione su un indirizzo privato o un server di staging che nessun altro utilizza, non ti serve affatto una certification authority; un certificato autofirmato richiede meno componenti e funziona anche offline.
Prerequisiti e i tre casi in cui la procedura non funziona prima ancora dell'avvio di Certbot
- Apache deve già pubblicare il sito tramite HTTP semplice. Il plugin Apache di Certbot modifica un sito esistente; non ne crea uno. Se parti da un VPS vuoto, configura prima lo stack LAMP su Ubuntu 24.04 e poi torna qui: questa guida è il capitolo TLS mancante.
- Serve un dominio pubblico con un record A che punti all'indirizzo del VPS. La challenge HTTP-01 di Let's Encrypt richiede che i server di validazione si connettano al server da Internet: niente homelab dietro NAT senza port forwarding, niente nomi
.locale niente indirizzi IP nudi.dig +short example.comdeve restituire l'indirizzo del VPS. Se hai modificato il DNS nell'ultima ora, attendi la scadenza del TTL del record precedente prima di richiedere il certificato. - Se esiste un record AAAA, deve essere corretto. Quando è pubblicato un record AAAA, Let's Encrypt preferisce IPv6. Un record AAAA obsoleto causa quindi il fallimento della validazione, anche se
curlfunziona correttamente dal laptop, probabilmente tramite IPv4. Pubblica un record AAAA corretto oppure non pubblicarne alcuno.
Le porte 80 e 443 devono essere aperte in ufw e nel firewall di rete del provider. La maggior parte dei pannelli di hosting dispone di un secondo firewall che il sistema operativo non vede. HTTP-01 esegue la validazione specificamente tramite la porta 80: questa procedura non può funzionare usando soltanto la porta 443.
sudo ufw allow "Apache Full"
sudo ufw statusCon questi prerequisiti, l'intera procedura richiede quindici minuti, dieci dei quali servono per leggere.
Certbot da Snap o da apt? Su 24.04, apt è finalmente una scelta valida
Certbot è passato alla distribuzione tramite snap diversi anni fa per una buona ragione: i pacchetti della distribuzione erano rimasti obsoleti. Ubuntu 20.04 includeva Certbot 0.40 e non lo ha mai aggiornato, mentre il progetto si è stancato di analizzare bug vecchi di cinque anni. In 24.04 questa ragione non sussiste più: l'archivio include Certbot 2.9.0, una release attuale, e unattended-upgrades lo mantiene aggiornato con le patch. Per questo sistema operativo consiglio di usare apt. Non è necessario il demone snapd, il plugin per Apache viene installato nella stessa transazione e il timer per il rinnovo si integra con systemd secondo il normale metodo Debian.
sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --versionRisultato corretto: certbot 2.9.0. Il pacchetto python3-certbot-apache è il plugin che legge e modifica le configurazioni di Apache; senza di esso, certbot --apache fallisce con The requested apache plugin does not appear to be installed.
Lo snap resta la scelta corretta in due casi: vuoi la versione più recente di Certbot il giorno stesso della release oppure ti serve un plugin DNS distribuito esclusivamente come snap, come accade per diversi plugin dei provider certbot-dns-*. Se scegli questa soluzione:
sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotQualunque soluzione tu scelga, non eseguire mai entrambe. Due installazioni significano due scheduler per il rinnovo che entrano in conflitto su /etc/letsencrypt e il certbot trovato dalla shell in PATH potrebbe non essere quello che gestisce i tuoi certificati. La riga apt remove riportata sopra non è un dettaglio facoltativo.
Il vhost che Certbot deve modificare deve già esistere: ServerName è il requisito fondamentale
certbot --apache individua il virtual host sulla porta 80 il cui ServerName o ServerAlias corrisponde a ciascun dominio -d passato, dimostra il controllo del dominio tramite quel virtual host e quindi crea una copia SSL dello stesso vhost. Se non esiste un ServerName corrispondente, non viene trovata alcuna corrispondenza. Inoltre, il 000-default.conf predefinito di Ubuntu viene distribuito con ServerName commentato. Quella singola riga commentata è il motivo più comune per cui il comando unico di questa guida non funziona.
Prima di usare Certbot, quindi, assegna al sito un vhost basato sul nome configurato correttamente. Crea /etc/apache2/sites-available/example.com.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>Abilitalo e verifica che Apache lo analizzi correttamente e instradi il nome verso quel vhost:
sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo apache2ctl -Sconfigtest deve stampare Syntax OK. Se stampa anche AH00558: apache2: Could not reliably determine the server's fully qualified domain name, si tratta di un avviso relativo al parametro global ServerName, non al tuo vhost. In questo caso è innocuo e può essere soppresso con echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf && sudo a2enconf servername && sudo systemctl reload apache2.
L'output di -S è il controllo importante. Deve comparire una riga come port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1) con alias www.example.com sotto di essa. Apache indica il symlink sites-enabled che ha effettivamente letto, non il file modificato in sites-available. Se example.com non è elencato sulla porta 80, neppure Certbot lo troverà.
Emetti il certificato: certbot --apache
sudo certbot --apache -d example.com -d www.example.comLa prima esecuzione richiede tre informazioni: un indirizzo email (utilizzato per l'account ACME e per gli avvisi urgenti della CA; Let's Encrypt non invia più avvisi sulla scadenza, quindi il monitoraggio dei rinnovi è a tuo carico), l'accettazione dei termini di Let's Encrypt e la scelta se condividere l'indirizzo email con EFF. La domanda sul redirect non viene più mostrata: da Certbot 2.0, l'installer Apache reindirizza per impostazione predefinita HTTP a HTTPS, che è il comportamento desiderato. Specifica --no-redirect solo se hai realmente bisogno che HTTP continui a pubblicare contenuti.
Il risultato corretto è simile al seguente. Leggilo senza limitarti a scorrerlo:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-10-14.
Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.comDietro questo messaggio, Certbot ha eseguito quattro operazioni: ha abilitato il modulo Apache ssl, se non era già abilitato; ha scritto example.com-le-ssl.conf, una copia del tuo virtual host in *:443 con SSLEngine on e i percorsi dei certificati; lo ha abilitato; infine, ha aggiunto un blocco RewriteRule al virtual host originale sulla porta 80, che reindirizza tutto a HTTPS con un codice 301. Il file originale del virtual host viene modificato, non sostituito, mentre la configurazione SSL corrispondente viene salvata accanto all'originale, dove puoi leggere ogni riga aggiunta.
Dove risiede realmente il certificato e perché non bisogna mai copiarlo
Tutto viene salvato in /etc/letsencrypt/live/example.com/: fullchain.pem (il certificato insieme alla catena degli intermedi, il file a cui i server devono puntare), privkey.pem (la chiave privata, leggibile solo da root), oltre a cert.pem e chain.pem per i software che richiedono i componenti separati. Questi file sono collegamenti simbolici a /etc/letsencrypt/archive/. Questo livello di indirezione gestisce il rinnovo: il rinnovo scrive i nuovi file in archive/ e aggiorna i collegamenti simbolici. Configura gli altri software affinché usino i percorsi live/: riceveranno automaticamente i certificati rinnovati. Se copi i file in un'altra posizione, provocherai un'interruzione del servizio dopo 90 giorni.
L'altro file importante è /etc/letsencrypt/renewal/example.com.conf. Registra come è stato emesso questo certificato, authenticator = apache, installer = apache e i domini. In questo modo il rinnovo può ripetere automaticamente la procedura, incluso il successivo ricaricamento di Apache.
Il rinnovo è già pianificato: verificalo, non ricrearlo
I certificati Let's Encrypt hanno una validità predefinita di 90 giorni e il pacchetto apt ha già installato i componenti necessari: un timer systemd che esegue Certbot due volte al giorno a orari casuali e rinnova i certificati che scadranno entro 30 giorni. Non aggiungere un cron job: un secondo meccanismo di pianificazione aggiunge solo rumore nei log e un'ulteriore esposizione ai limiti di frequenza.
systemctl list-timers certbot.timer
sudo certbot renew --dry-runIl primo comando mostra il timer attivo, con un orario NEXT nelle 24 ore successive. La pianificazione prevede due esecuzioni al giorno con un ritardo casuale, quindi l'orario esatto è deliberatamente imprevedibile. Nell'installazione tramite snap, il timer è snap.certbot.renew.timer. La dry run esegue una simulazione completa del rinnovo nell'ambiente di staging di Let's Encrypt, con una challenge reale ma senza emettere alcun certificato e senza consumare il rate limit. Un risultato corretto termina con:
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)Se la dry run fallisce, anche il rinnovo reale tra circa 60 giorni fallirà nello stesso modo. Risolvi il problema ora, mentre il certificato attuale ha ancora tutta la sua validità residua. La causa più comune è una regola del firewall aggiunta dopo l'emissione, che ha nuovamente chiuso la porta 80.
Verificare con curl e il contenuto dell’icona del lucchetto
curl -sI http://example.com | head -n 3
curl -I https://example.com
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -datesIl primo comando deve restituire HTTP/1.1 301 Moved Permanently con un’intestazione Location: https://example.com/: è il redirect installato da Certbot. Il secondo deve restituire HTTP/1.1 200 OK senza errori TLS da parte di curl. Il terzo stampa l’emittente, una riga O = Let's Encrypt con un CN breve come R12 o E7 e notAfter con una scadenza tra circa 90 giorni. Nel browser viene visualizzata l’icona del lucchetto; facendo clic su di essa viene mostrato lo stesso emittente. Se curl funziona ma il browser mostra un avviso, quasi certamente stai visualizzando una pagina memorizzata nella cache oppure il nome host non è quello corretto, non si tratta di un problema del certificato.
Più siti: un certificato SAN o un certificato per sito
Entrambe le opzioni funzionano e si rinnovano nello stesso modo. Per siti distinti sullo stesso server, esegui il comando di emissione una volta per sito. Ogni sito ottiene una propria directory in live/ e una propria configurazione di rinnovo. Un problema relativo a un dominio non impedisce mai il rinnovo degli altri. Questa è la mia impostazione predefinita.
Per un solo sito con più nomi, inseriscili in un unico certificato SAN. Un singolo certificato può contenere fino a 100 nomi. Hai già utilizzato questa configurazione sopra con example.com e www.example.com. Per aggiungere in seguito un nome a un certificato esistente, emetti nuovamente il certificato specificando il nome del certificato e l'elenco completo aggiornato:
sudo certbot --apache --cert-name example.com -d example.com -d www.example.com -d blog.example.comCertbot rileva la modifica dell'insieme di domini, chiede di confermare l'estensione e sostituisce il certificato in loco, mantenendo lo stesso percorso live/. Non è quindi necessario modificare altro. L'elenco sostituisce quello precedente, non lo estende: se ometti www da quel comando, il nuovo certificato lo esclude senza ulteriore avviso.
I certificati wildcard richiedono DNS-01 e, nella maggior parte dei casi, non sono necessari
HTTP-01 non può emettere *.example.com: pubblicare un file su un server web dimostra il controllo di un solo hostname, non di un intero namespace. I certificati wildcard richiedono la challenge DNS-01. Certbot imposta un record TXT su _acme-challenge.example.com. In pratica, questo richiede un plugin certbot-dns-* con credenziali API per il provider DNS oppure la modifica manuale dei record TXT a ogni rinnovo con --manual (una procedura impraticabile, da non usare come soluzione). La procedura completa, dalla gestione dei record TXT al plugin che esegue il rinnovo senza intervento, è disponibile in certificati wildcard con Certbot tramite DNS-01. Un consiglio pratico: se conosci già quattro sottodomini, un certificato SAN che li elenca tutti è più semplice di un certificato wildcard e non richiede chiavi API DNS archiviate sul server.
Modalità di errore e stringhe visualizzate
Certbot non si avvia perché la configurazione di Apache non è valida.
The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError('Error while running apache2ctl configtest.\n\nAction \'configtest\' failed.\nThe Apache error log may have more information.\n\nAH00526: Syntax error on line 12 of /etc/apache2/sites-enabled/example.com.conf')Il plugin esegue configtest prima di qualsiasi altra operazione e si interrompe se Apache rileva un errore. Le \n sono letterali perché Certbot stampa la rappresentazione repr dell'eccezione. Esegui direttamente sudo apache2ctl configtest: indica il file e la riga interessati. In genere il problema è un errore di battitura introdotto durante una modifica manuale, una SSLCertificateFile che punta a un percorso non più esistente oppure un modulo referenziato ma non abilitato. Correggi la configurazione finché il comando non stampa Syntax OK, quindi esegui nuovamente Certbot.
Nessun vhost corrisponde al dominio.
Unable to find a virtual host listening on port 80 which is currently the only challenge port.Questo è l'errore dovuto all'assenza di ServerName descritto in precedenza, rilevato durante la richiesta del certificato. Certbot ha cercato in tutti i vhost sulla porta 80 abilitati un ServerName/ServerAlias corrispondente al tuo -d, ma non ne ha trovato nessuno. sudo apache2ctl -S mostra come Apache instrada effettivamente le richieste. Aggiungi la riga ServerName al vhost corretto, ricarica la configurazione e riprova. Un caso simile si verifica quando la validazione raggiunge il vhost sbagliato: la risposta alla challenge restituisce Invalid response ... 404 perché un altro sito ha gestito la richiesta. La diagnosi è la stessa e anche lo strumento è lo stesso: apache2ctl -S.
La validazione va in timeout.
Certbot failed to authenticate some domains (authenticator: apache).
...
Detail: ...: Timeout during connect (likely firewall problem)Let's Encrypt non è riuscito ad aprire una connessione TCP alla porta 80 sull'indirizzo pubblicato dal DNS. Le cause più probabili, in ordine, sono: il firewall di rete del provider, distinto da ufw e configurato nel pannello di hosting; un insieme di regole ufw che consente soltanto la porta 443 o soltanto SSH; il DNS ancora puntato al server precedente; oppure il problema di un record AAAA obsoleto: i server di Let's Encrypt hanno tentato una connessione IPv6, ma il tuo server risponde soltanto su IPv4. Esegui il test dall'esterno del VPS: curl -I http://example.com dal tuo laptop riproduce ciò che vede il validatore.
Hai raggiunto un limite di frequenza dopo vari tentativi.
Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/Let's Encrypt consente 5 validazioni non riuscite per hostname, per account e per ora. Dopo la revisione dei limiti del 2025, il limite è un bucket che si ricarica: recuperi circa un tentativo ogni 12 minuti. Ripetere rapidamente i tentativi mentre il firewall è ancora configurato in modo errato lo esaurisce velocemente. Attendere risolve temporaneamente il problema, ma la correzione effettiva riguarda il metodo: dopo ogni errore, esegui il debug con l'ambiente staging finché la procedura non riesce.
sudo certbot certonly --apache --dry-run -d example.com -d www.example.comFai attenzione a certonly: --dry-run è accettato soltanto dai sottocomandi certonly e renew, mentre la forma semplice certbot --apache --dry-run rifiuta di avviarsi e mostra --dry-run currently only works with the 'certonly' or 'renew' subcommands. Il dry run esegue la validazione sull'ambiente staging, che ha limiti più ampi e non rilascia certificati reali; puoi quindi eseguire molti tentativi senza consumare i limiti di produzione. Esegui nuovamente il comando reale solo dopo il superamento del test nell'ambiente staging. Gli altri limiti, 50 certificati per dominio registrato alla settimana e 5 duplicati dello stesso insieme di nomi alla settimana, diventano rilevanti soltanto se uno script continua a emettere certificati in un ciclo.
Dopo aver attivato HTTPS, ricorda che il certificato protegge il trasporto, non il server: la porta 22 continua a ricevere tentativi di autenticazione con password per tutto il giorno. Abbinare questa configurazione a Fail2ban su Ubuntu 24.04 è il passo successivo più naturale nei prossimi 30 minuti.
FAQ
Devo installare Certbot con snap o apt per Apache su Ubuntu 24.04?
Usa apt. Ubuntu 24.04 distribuisce Certbot 2.9.0, una versione sufficientemente aggiornata per tutto ciò che viene descritto in questa guida, riceve gli aggiornamenti di sicurezza tramite unattended-upgrades e non richiede snapd. Scegli snap soltanto se ti serve subito la versione più recente o un plugin DNS distribuito esclusivamente come snap. In caso di passaggio, esegui prima apt remove certbot python3-certbot-apache, in modo che non coesistano due processi di rinnovo.
Perché Certbot mostra "Unable to find a virtual host listening on port 80"?
Perché non esiste un vhost sulla porta 80 abilitato con un ServerName o ServerAlias corrispondente al dominio passato con -d. Nel vhost predefinito di Ubuntu, ServerName è commentato. Esegui sudo apache2ctl -S, individua o crea il vhost che deve gestire il nome, aggiungi ServerName example.com, ricarica Apache ed esegui di nuovo Certbot.
Come posso risolvere "Timeout during connect (likely firewall problem)"?
Let's Encrypt non ha potuto raggiungere la porta 80 all'indirizzo pubblicato dal DNS. Controlla il firewall di rete configurato nel pannello del provider e ufw. Verifica che dig +short example.com restituisca questo VPS ed elimina o correggi eventuali record AAAA obsoleti. La validazione preferisce IPv6 quando è disponibile. Verifica la correzione dall'esterno del server con curl -I http://example.com, quindi esegui una prova con sudo certbot certonly --apache --dry-run -d example.com prima del rilascio effettivo.
Certbot rinnova automaticamente i certificati su Ubuntu 24.04?
Sì. Il pacchetto apt installa certbot.timer, un timer systemd che viene eseguito due volte al giorno e rinnova ogni certificato con scadenza entro 30 giorni, ricaricando Apache al termine. Lo snap usa snap.certbot.renew.timer per lo stesso compito. Verifica con systemctl list-timers certbot.timer ed esegui una prova con sudo certbot renew --dry-run. Non aggiungere un cron job personalizzato.
Come posso ottenere un certificato wildcard con Certbot e Apache?
I certificati wildcard richiedono la challenge DNS-01. Certbot deve creare un record TXT in _acme-challenge.example.com. Serve quindi un plugin certbot-dns-* con le credenziali API del provider DNS. L'alternativa --manual richiede di modificare manualmente i record TXT a ogni rinnovo. Se hai soltanto alcuni sottodomini noti, un certificato SAN che li elenca esplicitamente è più semplice e mantiene le chiavi API DNS fuori dal server.