1 14/05/2026 10 min

Su CentOS 8 Caddy ha senso quando vuoi un web server con configurazione semplice, TLS automatico e reverse proxy pulito, senza dover cucire a mano ogni dettaglio di certificati e ricariche. Il punto non è solo “installarlo”, ma farlo entrare in servizio in modo ordinato: repository corretto, unità systemd verificata, firewall aperto solo dove serve e configurazione di base già pensata per produzione.

Il vantaggio pratico è questo: Caddy parte con una sintassi minimale, gestisce HTTPS in autonomia e riduce il numero di pezzi mobili rispetto a uno stack classico con certificati separati e script di renew. Su CentOS 8 però conviene stare attenti a tre cose: repository compatibile, policy di rete del sistema e integrazione con gli altri servizi già presenti sulla macchina.

Repository e installazione su CentOS 8

CentOS 8 è una piattaforma EOL sul piano del supporto upstream, quindi il primo controllo non è estetico ma operativo: i repository devono essere raggiungibili e coerenti con la tua base sistema. Se il server è ancora in uso, la scelta più prudente è installare Caddy da repository ufficiale o da pacchetto statico verificato, evitando mix casuali tra repo terzi e binari presi al volo.

Prima di toccare il sistema, verifica la release e lo stato dei repository attivi:

cat /etc/centos-release
sudo dnf repolist
sudo dnf makecache

Se la cache fallisce, il problema non è ancora Caddy: hai un tema di connettività, mirror o repository obsoleti. Questo va chiuso prima di procedere, altrimenti ogni errore successivo diventa rumore.

Per installare Caddy via repository ufficiale, il flusso tipico è aggiungere la sorgente e poi installare il pacchetto. In ambienti dove il repository non è disponibile o non è affidabile, usa il binario ufficiale con checksum verificato e conserva il file sorgente del download per audit interno.

Esempio con repository esterno, da adattare alla policy del tuo ambiente:

sudo dnf install -y 'dnf-command(config-manager)'
sudo dnf config-manager --add-repo https://dl.cloudsmith.io/public/caddy/stable/rpm/caddy.repo
sudo dnf install -y caddy

Dopo l’installazione, controlla che il pacchetto sia davvero presente e che la versione sia quella attesa:

rpm -qi caddy
caddy version

Se il sistema usa un proxy aziendale o un filtro egress, il download del repository può fallire in modo parziale. In quel caso la verifica più rapida è confrontare l’accesso a URL del repository con curl -I e guardare se c’è un 200, un 3xx coerente o un errore TLS.

Avvio con systemd e controllo del servizio

Caddy su CentOS 8 si integra bene con systemd. Il primo obiettivo non è “farlo partire una volta”, ma assicurarsi che sia abilitato al boot, che il processo abbia permessi minimi e che eventuali errori di configurazione emergano subito nei log del servizio.

Controlla lo stato del servizio subito dopo l’installazione:

sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -b --no-pager

Lo stato atteso è active (running). Se vedi failed, la causa più frequente è una configurazione non valida in /etc/caddy/Caddyfile o una porta già occupata. Il journal di systemd è il primo posto da leggere, non l’ultimo.

Se vuoi abilitare l’avvio automatico:

sudo systemctl enable --now caddy

Verifica anche quale binario sta eseguendo davvero il servizio e con quali parametri:

systemctl cat caddy
ps -ef | grep '[c]addy'

Questa parte è utile quando in macchina convivono più copie del binario o quando qualcuno ha fatto un override dell’unità. In produzione, una unità systemd modificata senza traccia è un problema più serio di un errore di sintassi.

Caddyfile minimo per un sito statico

La configurazione base di Caddy è volutamente semplice. Per un sito statico, il file /etc/caddy/Caddyfile può partire da un blocco essenziale con root del sito e file server. Il punto forte è che la sintassi resta leggibile anche quando la macchina ospita più virtual host.

Esempio minimale:

example.com {
    root * /var/www/example.com
    file_server
}

Prima di ricaricare il servizio, valida la configurazione. Questo passaggio evita il classico errore di mettere in produzione una sintassi rotta e poi inseguire il problema sul browser.

Usa il validatore integrato:

sudo caddy validate --config /etc/caddy/Caddyfile

Se la validazione passa, ricarica in modo controllato:

sudo systemctl reload caddy

Il test reale è una richiesta HTTP locale e una richiesta esterna se il DNS è già pronto:

curl -I http://127.0.0.1
curl -I https://example.com

Se il sito non è ancora pubblicabile, puoi testare temporaneamente con curl -H 'Host: example.com' http://IP_DEL_SERVER. È un controllo utile quando il DNS non punta ancora al server o quando vuoi isolare il problema tra edge e origin.

Reverse proxy verso applicazioni PHP, Node o container

Uno dei casi d’uso più pratici è mettere Caddy davanti a un backend applicativo. In questo scenario Caddy fa da front-end TLS e da proxy verso l’app su una porta locale, lasciando al backend solo il lavoro applicativo. È una buona scelta per PHP-FPM dietro un web server diverso, per Node.js, Go o servizi containerizzati esposti in locale.

Esempio di reverse proxy verso un servizio in ascolto su 127.0.0.1:3000:

app.example.com {
    reverse_proxy 127.0.0.1:3000
}

Se il backend usa WebSocket o streaming, Caddy li gestisce senza configurazioni speciali nella maggior parte dei casi. La verifica concreta resta però la stessa: status code, header e log del backend. Quando qualcosa non torna, il problema sta spesso nel servizio a valle e non nel proxy.

Per un backend PHP classico, in molti casi Caddy viene usato davanti a PHP-FPM con un file server o con logica più articolata. Se il tuo stack è LEMP e vuoi sostituire Nginx, devi mappare con attenzione document root, gestione degli indici e passaggio dei file PHP al socket FastCGI. La configurazione varia in base alla struttura del progetto, quindi conviene partire dal caso più semplice e poi espandere.

Se il backend è in container, la pratica corretta è far parlare Caddy verso una porta pubblicata solo sul loopback o su una rete privata. Esporre direttamente il container sulla rete pubblica senza bisogno reale aumenta la superficie d’attacco e complica il troubleshooting.

TLS automatico, porte 80 e 443 e prerequisiti reali

Il motivo per cui Caddy viene scelto spesso è la gestione automatica dei certificati. Questo però funziona bene solo se il dominio risolve correttamente verso il server e se le porte 80 e 443 sono raggiungibili dall’esterno. Senza queste condizioni, il problema non è il certificato ma la raggiungibilità.

Prima di aspettarti l’emissione automatica, verifica DNS e connettività:

dig +short example.com
curl -I http://example.com
curl -vk https://example.com

Se il dominio punta correttamente ma il certificato non arriva, controlla il firewall locale. Su CentOS 8 con firewalld, le aperture minime sono queste:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

Se il server è dietro un bilanciatore o una CDN, devi considerare il layer esterno. In quel caso i problemi tipici sono: challenge ACME bloccata, HTTP forzato su HTTPS in modo incoerente, o un origin non raggiungibile dalla piattaforma a monte. Il controllo più rapido è guardare i log di Caddy e confrontarli con il traffico effettivo in ingresso.

Per capire se Caddy sta tentando la gestione TLS, il journal è la fonte migliore:

sudo journalctl -u caddy -f

Se compaiono errori su ACME, non forzare soluzioni improvvisate. Prima verifica che il record DNS sia corretto, che la porta 80 sia aperta e che nessun altro servizio stia rispondendo al posto di Caddy.

Permessi, directory e modello operativo pulito

La parte meno glamour ma più importante è il layout dei file. Caddy deve leggere il contenuto del sito e scrivere solo dove serve, ad esempio per log o cache applicative se previste. Il resto va lasciato fuori dal suo raggio d’azione.

Per un sito statico, una struttura ordinata può essere questa:

/var/www/example.com
/etc/caddy/Caddyfile
/var/log/caddy

Controlla ownership e permessi del contenuto servito:

sudo ls -ld /var/www/example.com
sudo find /var/www/example.com -maxdepth 2 -type f | head

Se usi SELinux in modalità enforcing, non ignorarlo. Su CentOS 8 è spesso la causa reale di un servizio che sembra configurato bene ma non riesce a leggere una directory o a connettersi a un backend locale. Quando qualcosa non va, i primi controlli sono:

getenforce
sudo ausearch -m avc -ts recent

Se trovi denial SELinux, la correzione giusta è una policy o un contesto appropriato, non un disable globale. Disattivare SELinux per “far funzionare” il servizio è una scorciatoia che sposta il problema e allarga la superficie d’attacco.

Logging e troubleshooting veloce

Quando Caddy non risponde come previsto, la sequenza corretta è: stato servizio, log, validazione configurazione, test locale, test remoto. Saltare direttamente al browser porta quasi sempre a diagnosi sbagliate.

Comandi base da tenere pronti:

sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -b --no-pager | tail -n 100
sudo caddy validate --config /etc/caddy/Caddyfile
curl -sv http://127.0.0.1
curl -sv https://example.com

Se vedi una pagina bianca o un 502, il proxy sta probabilmente funzionando ma il backend no. In quel caso il test da fare è direttamente sul servizio a valle, non su Caddy. Per esempio, se il backend ascolta su una porta locale, verifica che risponda davvero con curl o con una richiesta HTTP diretta alla porta interna.

Se il problema è un 404, il sospetto principale è il path root o il blocco del sito. Se invece compare un timeout, controlla saturazione, connessioni in coda e eventuali filtri di rete. Il comportamento di Caddy è semplice abbastanza da rendere evidenti gli errori a valle, purché tu guardi il layer giusto.

Scelte pratiche per produzione

In produzione conviene tenere Caddy con una configurazione essenziale e versionata. Ogni modifica al Caddyfile dovrebbe passare da validazione, reload e controllo dei log. Se il server ospita più siti, separa i blocchi in modo leggibile e mantieni una convenzione coerente per root, backend e log operativi.

Una buona regola è questa: se una modifica richiede più di pochi minuti per essere capita da un altro tecnico, la configurazione è già troppo densa. Caddy non va usato per nascondere complessità inutili, ma per renderla esplicita e gestibile.

Un esempio di approccio ordinato è mantenere un file per il front-end e un backend separato, con un flusso chiaro di verifica:

  1. validi la configurazione con caddy validate;
  2. ricarichi con systemctl reload caddy;
  3. controlli i log con journalctl -u caddy;
  4. verifichi il sito con curl -I dall’esterno.

Questo ordine riduce i falsi positivi e ti dice subito se il problema è nella configurazione, nel servizio o nella rete. È molto più utile che inseguire sintomi dal browser con tentativi casuali.

Quando Caddy non è la scelta giusta

Caddy è comodo, ma non è la risposta giusta a tutto. Se hai bisogno di una catena di moduli molto specifici, di un ecosistema già standardizzato su Apache o Nginx, o di integrazioni legacy particolari, il costo di migrazione può non valere il guadagno. In quei casi il criterio corretto è la compatibilità operativa, non la moda del momento.

Su CentOS 8, poi, la valutazione include anche il ciclo di vita della piattaforma. Installare un web server moderno su un sistema fuori supporto non risolve il problema strutturale del nodo. Se il server è ancora critico, la priorità vera è pianificare l’upgrade della base OS e non solo del front-end HTTP.

In sintesi operativa, Caddy su CentOS 8 funziona bene quando vuoi rapidità, TLS automatico e configurazione lineare. Funziona male solo quando lo tratti come una scatola magica e non controlli DNS, firewall, SELinux, backend e log. Il server web è spesso l’ultimo anello visibile, non il primo colpevole.