Come installare il server web Caddy con HTTPS automatico
Installare Caddy su Ubuntu dal repository ufficiale, scrivere un Caddyfile per siti statici e reverse proxy, capire i certificati automatici, systemd, i log e gli errori comuni nella migrazione da Nginx.

Caddy è un server web che ottiene e rinnova i certificati TLS per impostazione predefinita. Per un VPS piccolo che ospita uno o due domini, questo elimina un’intera classe di timer Certbot e file di snippet Nginx. Il linguaggio di configurazione (Caddyfile) è breve. Reverse proxy, gzip e HTTP/2 sono funzioni normali, non un weekend di moduli extra.
Nginx resta la scelta giusta per alcuni team: avete già config collaudate, o vi serve un modulo molto specifico. Questa guida è per l’altro caso comune: volete un HTTPS che funzioni su un VPS Hiddence nuovo senza memorizzare snippet include. Installiamo Caddy dal repo apt ufficiale, spieghiamo come parla con Let's Encrypt, serviamo un sito statico, facciamo proxy di un’app locale, ospitiamo più domini, guardiamo i log e copriamo le solite lotte per la porta 80 con Apache o un Nginx vecchio.
Quando Caddy è una buona scelta
L’HTTPS automatico è il titolo, ma il guadagno quotidiano sono meno parti in movimento. Caddy ascolta su 80 e 443, reindirizza HTTP verso HTTPS e memorizza i certificati nella propria directory dati. Ti serve comunque un dominio che punti al VPS. Non devi comunque rompere ACME (firewall 80/tcp, nessun altro processo che ruba :80). I certificati wildcard richiedono un modulo provider DNS: è un percorso più lungo di un certificato per un solo host.
- Reindirizzamento HTTP→HTTPS automatico e rinnovo dei certificati
- Caddyfile leggibile invece di lunghi blocchi server
- Reverse proxy capace per Node, Python, PHP-FPM con config extra, o backend Docker
- HTTP/2 e default TLS moderni senza un foglio di cipher
- Unità systemd dal pacchetto ufficiale
Requisiti
Un dominio deve risolvere su questo VPS prima che Caddy possa dimostrare ACME HTTP-01. Se il DNS sta ancora propagandosi, Caddy fallirà l’emissione e riproverà: sembra «Caddy è rotto» quando è solo DNS. Ferma prima Apache o Nginx se possiedono 80/443.
- Ubuntu 22.04 o 24.04
- Un record A del dominio verso l’IP del VPS (e AAAA se usi IPv6)
- Porte 80 e 443 libere e consentite nel firewall
- Root o sudo
Passo 1: Installare Caddy dal repository ufficiale
Non installare un Caddy vecchio a caso da Ubuntu Universe se vuoi il comportamento TLS e ACME attuale. Il progetto Caddy documenta una sorgente apt. Dopo l’installazione esiste l’utente caddy e il servizio è abilitato.
ssh root@YOUR_VPS_IP
apt update && apt -y install debian-keyring debian-archive-keyring apt-transport-https curl gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update
apt -y install caddy
caddy version
systemctl status caddy --no-pagerPasso 2: Primo Caddyfile — sito statico
Il Caddyfile predefinito è /etc/caddy/Caddyfile. Sostituiscilo con il tuo dominio. Caddy proverà a ottenere un certificato appena la config si carica se l’hostname non è localhost. Metti i file del sito in una directory leggibile dall’utente caddy (spesso permessi in stile www-data, ma il pacchetto usa l’utente caddy).
mkdir -p /var/www/example
echo '<h1>It works</h1>' > /var/www/example/index.html
chown -R caddy:caddy /var/www/example
cat >/etc/caddy/Caddyfile <<'EOF'
example.com {
root * /var/www/example
file_server
encode gzip
}
EOF
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
# Watch issuance:
journalctl -u caddy -fPasso 3: Reverse proxy di un’applicazione locale
Se Gunicorn, Node o Docker ascoltano su 127.0.0.1:8000, Caddy deve essere l’unico processo pubblico. La direttiva reverse_proxy inoltra Host e le intestazioni X-Forwarded-* in modo ragionevole per la maggior parte delle app. Se l’app genera URL HTTP assolute, imposta i flag di proxy fidato / HTTPS nell’app (Django SECURE_PROXY_SSL_HEADER, Express trust proxy e così via).
app.example.com {
encode gzip
reverse_proxy 127.0.0.1:8000
}
# Several hosts in one file are normal:
# blog.example.com {
# root * /var/www/blog
# file_server
# }Passo 4: Firewall e systemd
Consenti 80 e 443. L’unità di Caddy è caddy.service; un reload basta dopo le modifiche al Caddyfile se il processo è sano. Se cambi variabili d’ambiente per un plugin DNS, un riavvio completo è più chiaro. I certificati vivono per impostazione predefinita sotto /var/lib/caddy/.local/share/caddy/: includi quel percorso nei backup se ti interessano i limiti di frequenza in una reinstallazione.
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
systemctl enable --now caddy
systemctl reload caddy
# Backup cert storage (path may vary slightly by version):
ls -la /var/lib/caddy/Passo 5: Log, compressione e intestazioni
I log di accesso aiutano quando un bot martella un percorso o quando fai debug dei 404. Puoi registrare per sito. Aggiungi intestazioni di sicurezza se ospiti un’app browser; non copiare un enorme pacchetto di intestazioni senza capire HSTS (una volta impostato un max-age lungo, i browser lo ricordano).
example.com {
root * /var/www/example
file_server
encode gzip
log {
output file /var/log/caddy/example.log
}
header {
X-Content-Type-Options nosniff
Referrer-Policy no-referrer-when-downgrade
-Server
}
}
mkdir -p /var/log/caddy
chown caddy:caddy /var/log/caddy
systemctl reload caddyPasso 6: PHP e altri extra
Caddy può parlare con PHP-FPM con la direttiva php_fastcgi. Basta per molti hosting WordPress o Laravel, ma ti serve ancora php-fpm installato e un percorso socket che coincida. Se hai già un config PHP Nginx perfetto, migrare in una serata è facoltativo: Caddy brilla di più su reverse proxy + statico + TLS automatico.
example.com {
root * /var/www/example
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
}
# Confirm FPM is running:
systemctl status php8.3-fpmMigrare da Nginx senza sorprese di downtime
Ferma Nginx prima di avviare Caddy o si batteranno per 80/443. Abbassa il TTL DNS il giorno prima se stai anche spostando gli IP. Prova con curl --resolve per colpire il nuovo VPS prima di cambiare il record A. Tieni i config Nginx in git per una settimana nel caso serva tornare indietro.
- systemctl stop nginx && systemctl disable nginx
- Installa Caddy, valida il Caddyfile, avvia Caddy
- curl -I --resolve example.com:443:NEW_IP https://example.com
- Solo allora cambia il DNS se l’IP è nuovo
- La riemissione è automatica; non far girare anche Certbot contro lo stesso hostname
Risoluzione dei problemi
I fallimenti ACME sono quasi sempre DNS, firewall o un altro servizio sulla porta 80. Le righe di log di Caddy menzionano tls.obtain. Se il sito funziona in HTTP ma non in HTTPS, l’emissione non è mai stata completata. Se vedi troppi certificati, hai toccato i limiti di frequenza Let's Encrypt: usa la CA di staging per i test, non quella di produzione.
- validate fallisce: sintassi del Caddyfile, graffa mancante
- permission denied su root: chown caddy per la directory del sito
- bind: address already in use — ss -tulpn | grep -E ':80|:443'
- timeout del certificato: dig +short del dominio dal VPS, ufw allow 80
- 502 reverse_proxy: backend spento, o hai fatto proxy verso localhost da una rete di container in modo errato
Note di sicurezza
I default TLS di Caddy sono conservativi. Il tuo lavoro è la sicurezza dell’applicazione e SSH. Non attivare l’API di amministrazione Caddy su un’interfaccia pubblica. L’endpoint di amministrazione predefinito è locale; lascialo così. Se usi un Caddyfile da internet, leggi ogni matcher: uno snippet che fa reverse_proxy di /* verso un IP interno può diventare un proxy aperto.
- Non esporre l’API di amministrazione
- Tieni il pacchetto aggiornato
- HSTS solo dopo esserti assicurato che HTTPS funzioni per tutti gli hostname
- Separa gli hostname di test e di produzione per proteggere i limiti di frequenza ACME
Consigli
- caddy fmt --overwrite /etc/caddy/Caddyfile tiene il file leggibile
- Usa snippet import quando hai molti siti simili
- Per Docker è comune l’immagine caddy:alpine con un Caddyfile montato
- I certificati wildcard richiedono un modulo DNS e un token API: proteggi quel token
- Leggi journalctl -u caddy prima di riscrivere l’intero file
Caddy su un VPS è: pacchetto ufficiale, un Caddyfile breve, porte 80/443 aperte, DNS già puntato al server e reload systemd dopo le modifiche. Usalo come server di file statici o come reverse proxy davanti a Gunicorn, Node o Docker. L’HTTPS automatico funziona quando ACME può rispondere sulla porta 80; se l’emissione fallisce, sistema DNS e conflitti di porta prima di incolpare Caddy. Fai il backup di /var/lib/caddy se reinstalli spesso.