Certbot è il client ACME ufficiale di Let’s Encrypt per ottenere e rinnovare certificati SSL/TLS gratuiti. Questa guida copre l’installazione via Snap, la configurazione automatica su Nginx, i certificati wildcard con DNS challenge, le best practice TLS moderne e il troubleshooting degli errori più comuni.
L’articolo è aggiornato a marzo 2026 e testato su Ubuntu 22.04/24.04 LTS con Nginx. Se gestisci server web e devi implementare HTTPS — o hai ancora una configurazione Certbot basata sul vecchio PPA — qui trovi tutto quello che serve per un setup moderno e automatizzato.
Prerequisiti e architettura TLS moderna
Dal 2020 ad oggi il panorama SSL/TLS è cambiato radicalmente. TLS 1.3 è diventato lo standard de facto, il PPA di Certbot è stato deprecato in favore di Snap, e il protocollo ACME v2 supporta nativamente i certificati wildcard. Se hai una configurazione Certbot installata via apt dal vecchio PPA, è il momento di migrare.
Cosa serve per seguire questa guida:
- Un server Ubuntu 22.04 o 24.04 LTS con accesso root/sudo
- Nginx installato e funzionante con almeno un server block configurato
- Un dominio con record DNS A/AAAA che punta al server
- Porta 80 raggiungibile dall’esterno (per la validazione HTTP-01)
L’infrastruttura Let’s Encrypt utilizza il protocollo ACME (Automatic Certificate Management Environment, RFC 8555) per verificare il controllo del dominio e rilasciare certificati. Certbot automatizza l’intero flusso: validazione, emissione, installazione nella configurazione Nginx e rinnovo periodico.
Installare Certbot via Snap
Dal 2021 il metodo ufficiale per installare Certbot è tramite Snap. Il vecchio PPA (ppa:certbot/certbot) non riceve più aggiornamenti. Snap garantisce auto-update, isolamento dal sistema e una singola fonte di distribuzione mantenuta dalla EFF.
Rimuovere vecchie installazioni
Se hai Certbot installato via apt o PPA, rimuovilo prima di procedere con Snap:
sudo apt remove certbot python3-certbot-nginx -y
sudo add-apt-repository --remove ppa:certbot/certbot -y 2>/dev/null
sudo apt autoremove -y
Installare Certbot con Snap
# Aggiorna snapd
sudo snap install core; sudo snap refresh core
# Installa Certbot
sudo snap install --classic certbot
# Crea il symlink per usare certbot da qualsiasi path
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Verificare l’installazione
certbot --version
# Output atteso: certbot 3.x.x
snap info certbot
# Mostra versione, canale, ultimo aggiornamento
Snap aggiorna Certbot automaticamente. Non serve configurare cron job per gli update del client — solo per il rinnovo dei certificati (che Snap gestisce anch’esso tramite timer systemd).
Ottenere un certificato SSL per Nginx
Certbot offre tre modalità di validazione. Il metodo da scegliere dipende dalla configurazione del server e dal livello di automazione desiderato.
Metodo automatico con il plugin –nginx
Il modo più rapido. Certbot modifica automaticamente i server block di Nginx aggiungendo le direttive SSL, il redirect HTTP→HTTPS e i path ai certificati:
sudo certbot --nginx -d example.com -d www.example.com
Certbot esegue queste operazioni in sequenza:
- Analizza i server block in
/etc/nginx/sites-enabled/ - Richiede il certificato a Let’s Encrypt tramite challenge HTTP-01
- Aggiunge le direttive
ssl_certificateessl_certificate_keyal server block - Configura il redirect 301 da HTTP a HTTPS (se confermi)
- Ricarica Nginx con
nginx -t && systemctl reload nginx
Dopo l’esecuzione, la configurazione Nginx includerà automaticamente linee come queste:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
Metodo webroot
Se non vuoi che Certbot modifichi la configurazione Nginx — ad esempio su server con reverse proxy o configurazioni custom complesse — usa certonly --webroot:
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com
Certbot crea un file temporaneo nella directory .well-known/acme-challenge/ della webroot. Il server Let’s Encrypt verifica il file via HTTP e rilascia il certificato. Dovrai poi configurare manualmente i path SSL in Nginx.
Metodo standalone
Certbot avvia un web server temporaneo sulla porta 80. Utile per servizi non-web (mail server, VPN) o quando Nginx non è ancora installato:
# Ferma temporaneamente Nginx se occupa la porta 80
sudo systemctl stop nginx
sudo certbot certonly --standalone -d mail.example.com
sudo systemctl start nginx
Certificati wildcard con DNS challenge
I certificati wildcard (*.example.com) coprono tutti i sottodomini di primo livello. Richiedono la validazione DNS-01 — l’unico metodo che Let’s Encrypt accetta per i wildcard.
Come funziona la validazione DNS-01
Certbot richiede la creazione di un record TXT con nome _acme-challenge.example.com e un valore token fornito durante il processo. Let’s Encrypt interroga il DNS per verificare il record e rilascia il certificato. A differenza di HTTP-01, non richiede che il server sia raggiungibile sulla porta 80.
Ottenere un wildcard certificate (manuale)
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.example.com" -d example.com
Certbot mostrerà il valore del record TXT da creare. Dopo averlo aggiunto nel pannello DNS del registrar, premi Enter per procedere. Verifica la propagazione prima di confermare:
dig _acme-challenge.example.com TXT +short
Nota: con il metodo --manual il rinnovo automatico non funziona — ad ogni rinnovo occorre aggiornare il record TXT manualmente. Per automatizzare, usa un plugin DNS.
Automatizzare con plugin DNS
I plugin DNS di Certbot interagiscono con le API del provider DNS per creare e rimuovere automaticamente i record TXT. Esempio con Cloudflare:
# Installa il plugin Cloudflare
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
# Crea il file di credenziali
sudo mkdir -p /etc/letsencrypt
sudo cat > /etc/letsencrypt/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
# Ottieni il certificato wildcard
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.example.com" -d example.com
Con questa configurazione il rinnovo automatico funziona senza intervento manuale.
Plugin DNS disponibili via Snap:
| Plugin | Provider DNS | Pacchetto Snap |
|---|---|---|
| certbot-dns-cloudflare | Cloudflare | certbot-dns-cloudflare |
| certbot-dns-route53 | AWS Route 53 | certbot-dns-route53 |
| certbot-dns-google | Google Cloud DNS | certbot-dns-google |
| certbot-dns-digitalocean | DigitalOcean | certbot-dns-digitalocean |
| certbot-dns-ovh | OVH | certbot-dns-ovh |
| certbot-dns-linode | Linode/Akamai | certbot-dns-linode |
Configurazione Nginx ottimale per SSL/TLS
Certbot configura automaticamente SSL con impostazioni ragionevoli. Tuttavia, per deployment ad alte prestazioni e massima sicurezza, alcune direttive meritano un tuning manuale. La configurazione di riferimento è il Mozilla SSL Configuration Generator (profilo "Intermediate" per compatibilità, "Modern" per massima sicurezza).
Protocolli e cifrari: TLS 1.2+ e TLS 1.3
# /etc/nginx/conf.d/ssl-hardening.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
TLS 1.0 e 1.1 sono deprecati da tutti i browser moderni dal 2020. ssl_prefer_server_ciphers off è la scelta corretta con TLS 1.3 perché il client negozia il cifrario più efficiente disponibile.
OCSP Stapling
OCSP Stapling elimina la necessità per il browser di contattare la CA per verificare la validità del certificato. Riduce la latenza del TLS handshake e migliora la privacy dell'utente:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
Verifica che OCSP Stapling sia attivo:
openssl s_client -connect example.com:443 -servername example.com -status 2>/dev/null | grep -A 2 "OCSP Response Status"
HSTS e HSTS Preload
HSTS (HTTP Strict Transport Security) istruisce il browser a connettersi sempre via HTTPS, prevenendo attacchi di downgrade SSL stripping:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Nota: includeSubDomains forza HTTPS su tutti i sottodomini. L'opzione preload consente di registrare il dominio nella HSTS Preload List integrata nei browser. Questa operazione è praticamente irreversibile — assicurati che tutti i sottodomini supportino HTTPS prima di attivarla.
CAA Record DNS
Il record CAA (Certification Authority Authorization) limita quali CA possono emettere certificati per il dominio. È una misura di sicurezza aggiuntiva che previene l'emissione non autorizzata:
# Record DNS da aggiungere nel pannello del registrar
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issuewild "letsencrypt.org"
example.com. IN CAA 0 iodef "mailto:[email protected]"
issue autorizza l'emissione di certificati standard, issuewild autorizza i wildcard, iodef specifica dove inviare le notifiche di violazione. Verifica la configurazione:
dig example.com CAA +short
Rinnovo automatico dei certificati
I certificati Let's Encrypt scadono dopo 90 giorni. Certbot installato via Snap configura automaticamente un timer systemd che esegue il rinnovo due volte al giorno — il rinnovo effettivo avviene solo quando mancano meno di 30 giorni alla scadenza.
Verificare il timer systemd
# Verifica che il timer sia attivo
systemctl list-timers | grep certbot
# Output atteso:
# snap.certbot.renew.timer ... snap.certbot.renew.service
# Test di rinnovo (senza effettuare il rinnovo reale)
sudo certbot renew --dry-run
Se --dry-run completa senza errori, il rinnovo automatico funzionerà correttamente.
Hook di deploy post-rinnovo
Dopo il rinnovo del certificato, Nginx deve ricaricare la configurazione per servire il nuovo certificato. Configura un deploy hook:
# Metodo 1: flag --deploy-hook
sudo certbot renew --deploy-hook "systemctl reload nginx"
# Metodo 2: script persistente nella directory hooks
sudo cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Il metodo 2 è preferibile perché il hook viene eseguito ad ogni rinnovo senza dover passare il flag manualmente.
Monitorare la scadenza
# Lista tutti i certificati gestiti da Certbot
sudo certbot certificates
# Verifica la scadenza da remoto
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
Gestione multi-dominio e certificati esistenti
Aggiungere domini a un certificato esistente
sudo certbot certonly --nginx --expand \
-d example.com -d www.example.com -d blog.example.com
Il flag --expand aggiunge i nuovi domini al certificato esistente senza revocarlo. Tutti i domini precedenti devono essere inclusi nel comando.
Revocare e eliminare un certificato
# Revoca il certificato (lo invalida presso Let's Encrypt)
sudo certbot revoke --cert-name example.com
# Elimina i file locali del certificato
sudo certbot delete --cert-name example.com
La revoca è necessaria solo se la chiave privata è stata compromessa. Per un semplice cleanup locale, certbot delete è sufficiente.
Rate limit di Let's Encrypt
Let's Encrypt impone limiti per prevenire abusi. Conoscerli è fondamentale per evitare blocchi durante deployment su larga scala:
| Limite | Valore | Periodo |
|---|---|---|
| Certificati per dominio registrato | 50 | Settimana |
| Certificati duplicati | 5 | Settimana |
| Nuovi ordini | 300 | 3 ore |
| Validazioni fallite | 5 | Ora per account/hostname/tipo |
| Account per IP | 10 | 3 ore |
Per test e sviluppo, usa sempre l'ambiente staging che non ha questi limiti:
sudo certbot certonly --nginx --staging -d test.example.com
I certificati staging non sono trusted dai browser, ma il flusso ACME è identico a quello di produzione.
Troubleshooting: errori comuni e soluzioni
Challenge failed — porta 80 bloccata
L'errore più frequente. La validazione HTTP-01 richiede che Let's Encrypt raggiunga il server sulla porta 80. Verifica:
# Controlla cosa occupa la porta 80
sudo ss -tlnp | grep :80
# Verifica il firewall
sudo ufw status
sudo iptables -L -n | grep 80
# Testa la raggiungibilità dall'esterno
curl -I http://example.com/.well-known/acme-challenge/test
Cause comuni: firewall UFW/iptables che blocca la porta 80, un altro servizio (Apache, Varnish) che occupa la porta, o un cloud firewall (security group AWS, regola GCP) che non consente il traffico HTTP in ingresso.
Too many certificates already issued
Hai superato il rate limit di 50 certificati/settimana per dominio. Soluzioni:
- Attendi il reset settimanale del contatore
- Usa
--stagingper i test futuri - Consolida i domini in un unico certificato SAN (Subject Alternative Name) invece di emettere un certificato per ogni sottodominio
DNS problem: NXDOMAIN (wildcard)
Il record TXT _acme-challenge non è stato trovato. Cause:
- Propagazione DNS non completata — attendi 2-5 minuti e verifica con
dig _acme-challenge.example.com TXT +short - TTL troppo alto sul record — riduci il TTL a 60-120 secondi prima di procedere
- Record TXT creato nel dominio sbagliato (es.
_acme-challenge.example.com.example.com)
Certificato rinnovato ma Nginx serve quello vecchio
Nginx carica i certificati in memoria all'avvio. Dopo il rinnovo, serve un reload:
sudo nginx -t && sudo systemctl reload nginx
Se il problema persiste, verifica che il deploy hook sia configurato (vedi sezione rinnovo automatico). Controlla i log di Certbot per confermare il rinnovo:
sudo cat /var/log/letsencrypt/letsencrypt.log | tail -50
Mixed content dopo migrazione a HTTPS
Dopo aver attivato HTTPS, il sito carica ancora risorse via HTTP. Su WordPress questo è un problema frequente — URL hardcoded nel database che puntano a http://. Soluzione:
# Search-replace nel database WordPress (con WP-CLI)
wp search-replace 'http://example.com' 'https://example.com' --dry-run
wp search-replace 'http://example.com' 'https://example.com'
Alternative a Certbot e Let's Encrypt
Certbot è lo standard, ma non è l'unica opzione. In base al contesto operativo, queste alternative possono essere più adatte.
acme.sh
Client ACME scritto interamente in shell script. Non richiede root, supporta oltre 150 provider DNS per la validazione automatica, e funziona su qualsiasi sistema Unix-like. Ideale per ambienti dove Snap non è disponibile o dove si preferisce evitare dipendenze esterne.
Caddy Server
Web server con HTTPS automatico integrato. Caddy ottiene e rinnova certificati Let's Encrypt senza alcuna configurazione — basta specificare il dominio nel Caddyfile. Zero config, zero manutenzione. Ottimo per progetti greenfield dove non c'è un vincolo su Nginx.
Traefik
Reverse proxy pensato per ambienti containerizzati (Docker, Kubernetes). Gestisce automaticamente i certificati per ogni servizio esposto, con supporto nativo ACME e DNS challenge. La scelta naturale per architetture a microservizi.
Certificati gestiti dal cloud provider
AWS Certificate Manager, Cloudflare, Google-managed certificates. Certificati gratuiti gestiti dal provider, con rinnovo automatico e integrazione nativa con load balancer e CDN. Non richiedono Certbot sul server.
| Soluzione | Caso d'uso ideale | Complessità | Auto-rinnovo |
|---|---|---|---|
| Certbot + Nginx | VPS/server dedicati con Nginx | Bassa | Si (systemd) |
| acme.sh | Ambienti senza Snap, script custom | Media | Si (cron) |
| Caddy | Progetti nuovi, semplicità massima | Minima | Si (built-in) |
| Traefik | Docker/Kubernetes, microservizi | Media-alta | Si (built-in) |
| Cloud-managed | Infrastruttura su AWS/GCP/Cloudflare | Minima | Si (provider) |
Verifica e test del certificato
Test da riga di comando
# Informazioni complete sul certificato
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text
# Solo date di validità
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
# Header di risposta HTTPS
curl -vI https://example.com 2>&1 | grep -E "SSL|TLS|subject|issuer|expire"
Tool online di analisi
- SSL Labs Server Test (ssllabs.com/ssltest) — analisi approfondita della configurazione TLS con rating A-F. Verifica protocolli, cifrari, vulnerabilità note
- Mozilla Observatory (observatory.mozilla.org) — valuta la sicurezza complessiva degli header HTTP, inclusi HSTS, CSP, X-Frame-Options
- Hardenize (hardenize.com) — combina analisi TLS, DNS, email security in un unico report
Certificate Transparency logs
Certificate Transparency (CT) è un framework che registra tutti i certificati emessi in log pubblici. Utile per monitorare emissioni non autorizzate per il proprio dominio:
- crt.sh — ricerca certificati emessi per un dominio nei CT log
- Google Certificate Transparency Report — viewer ufficiale Google
Risorse e riferimenti
- Certbot — documentazione ufficiale EFF
- Let's Encrypt — documentazione
- Let's Encrypt — rate limits
- Mozilla SSL Configuration Generator
- RFC 8555 — ACME Protocol
Articoli correlati su questo blog:
Articoli correlati
Autore
Mi chiamo Giovanni Sacheli e dal 2009 aiuto le aziende a farsi trovare online. Sono specializzato in SEO tecnica e PPC, competenze che applico quotidianamente nella mia agenzia, Searcus Swiss Sagl. Mi piace sviluppare strumenti a supporto del mio lavoro, ho creato SEOdata.app e cluster.army e co-scritto il libro SEO Audit Avanzato. Curo maniacalmente questo blog per colleghi e appassionati, dove mi "appunto" quello che imparo. Sono un NERD anni '80, motociclista e orgoglioso papà di due bambini.
Link:
Giovanni Sacheli
SEO Audit Avanzato
Searcus Swiss Sagl
SEOdata.app
cluster.army