1 25/05/2026 11 min

Su AlmaLinux 8 e Rocky Linux 8 Caddy si installa in modo pulito usando il repository ufficiale, senza pacchetti esterni o workaround strani. La differenza vera non è l’installazione in sé, ma come lo integri con firewalld, SELinux, systemd e l’eventuale reverse proxy verso applicazioni PHP, Node.js o servizi interni.

Se l’obiettivo è pubblicare un sito con HTTPS automatico, Caddy è una scelta pratica: gestisce certificati Let’s Encrypt senza script aggiuntivi e riduce il numero di pezzi da mantenere. Se invece devi esporre un servizio già esistente, conviene ragionare subito su upstream, porte, log e policy di rete, così eviti di installare il server e poi scoprire che il problema è a monte.

Quando ha senso usare Caddy su AlmaLinux 8 e Rocky Linux 8

Caddy torna utile quando vuoi un web server/reverse proxy con configurazione leggibile e TLS automatico. Su RHEL-like 8 lo scenario tipico è questo: una VM o un server fisico con IP pubblico, DNS già puntato, porte 80 e 443 aperte, e un backend locale su 127.0.0.1 o su una rete privata.

Non è invece il primo candidato se ti serve una configurazione estremamente articolata di moduli legacy, compatibilità con vecchi plugin Apache, o una governance centralizzata già basata su Nginx con tool di automazione consolidati. Caddy è semplice, ma la semplicità funziona bene finché accetti il suo modello operativo.

Prerequisiti minimi prima dell’installazione

Prima di installare il pacchetto, verifica questi punti: hostname corretto, record DNS già propagati, porte 80/443 disponibili, e nessun altro servizio che occupi le stesse porte. Se il server è dietro NAT o bilanciamento esterno, devi conoscere anche il percorso reale del traffico, perché il certificato TLS dipende dal fatto che la validazione HTTP o TLS-ALPN possa raggiungere il nodo giusto.

Controlli rapidi utili:

hostnamectl
resolvectl status 2>/dev/null || cat /etc/resolv.conf
ss -lntp | egrep ':(80|443)\s'
firewall-cmd --state

Se `ss` mostra già un processo in ascolto su 80 o 443, devi decidere subito se fermarlo o spostare Caddy su un’altra porta temporanea. In produzione, la prima opzione è la più pulita, ma va valutato il blast radius: se stai sostituendo Apache o Nginx, il rollback deve essere già pronto.

Repository ufficiale Caddy su EL8

Su AlmaLinux 8 e Rocky Linux 8 il modo corretto è usare il repository ufficiale. Evita di pescare binari casuali o pacchetti mantenuti da terzi senza capire il ciclo di aggiornamento. Il vantaggio del repo ufficiale è doppio: installi una build coerente e ricevi aggiornamenti con un flusso prevedibile.

Procedura base:

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

Se il repository non viene aggiunto, il problema di solito è uno tra DNS, proxy aziendale o policy di uscita verso Internet. In quel caso verifica con `curl -I` l’URL del repo e controlla i log di `dnf` in `/var/log/dnf.log` e `/var/log/dnf.rpm.log`.

Verifica finale del pacchetto installato:

caddy version
rpm -qi caddy

Se `caddy version` risponde con una versione coerente e `rpm -qi` mostra il vendor atteso, la base è ok. A questo punto puoi passare alla configurazione senza improvvisare.

Servizio systemd e stato iniziale

Il pacchetto installa anche l’unità systemd. Prima di toccare la configurazione, controlla che il servizio parta e che il binario legga il file di default nel posto previsto.

sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 50 --no-pager

Il file principale è in `/etc/caddy/Caddyfile`. Il servizio gira con utente dedicato e non va trattato come un demone generico da lanciare a mano in sessione SSH. Se devi fare un cambio, usa il reload controllato e conserva una copia del file precedente.

Prima modifica sensata: salva un backup del file esistente.

sudo cp -a /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%F_%H%M%S)

Configurazione minima per un sito statico

Se vuoi servire contenuti statici, la configurazione minima è molto corta. Il punto non è scrivere meno righe possibile, ma tenere chiaro il mapping tra dominio, root documentale e logica TLS.

example.com { reverse_proxy 127.0.0.1:8080 encode zstd gzip log { output file /var/log/caddy/access.log format json }
}

Se stai pubblicando un contenuto statico, sostituisci `reverse_proxy` con `root` e `file_server`.

example.com { root * /var/www/example.com/html file_server encode zstd gzip log { output file /var/log/caddy/access.log format json }
}

Dopo aver salvato il file, verifica la sintassi prima di ricaricare il servizio.

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

Se la validazione fallisce, non forzare il restart. Il vantaggio di Caddy è proprio il controllo strutturale prima del reload; sprecarlo significa rendersi la vita più difficile del necessario.

Reverse proxy verso applicazioni locali

Lo scenario più comune su EL8 è Caddy davanti a un’app che ascolta su `127.0.0.1:3000`, `127.0.0.1:8080` o su socket TCP interno. In questo caso Caddy fa da terminazione TLS e inoltra le richieste al backend. La scelta giusta è tenere il backend non esposto su Internet, così riduci la superficie d’attacco e semplifichi il firewall.

app.example.com { reverse_proxy 127.0.0.1:3000 log { output file /var/log/caddy/app-access.log format json }
}

Se il backend usa WebSocket o streaming, Caddy lo gestisce senza configurazioni speciali nella maggior parte dei casi. Se invece l’app dipende da header specifici, controlla che vengano passati correttamente e che il backend sia configurato per fidarsi del proxy solo dove serve.

Per verificare il flusso end-to-end, prova una richiesta locale e una remota:

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

Se la risposta locale funziona ma quella remota no, il problema è quasi sempre nel layer rete: DNS, firewall, security group, NAT o certificato. Se entrambe falliscono, guarda i log di Caddy e del backend prima di cambiare config a caso.

Firewall: aprire solo ciò che serve

Su AlmaLinux e Rocky, `firewalld` è il caso normale. Caddy ha bisogno di 80 e 443, e basta, salvo esigenze particolari. Aprire porte extra perché “magari servono” è una cattiva abitudine che poi crea rumore in audit e incidenti inutili.

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

Se Caddy ascolta su porte diverse per test, apri solo quelle in modo temporaneo e documenta il rollback. In produzione, il test su porta alternativa va considerato una deviazione controllata, non una configurazione stabile.

SELinux: il punto che spesso blocca il backend

Su EL8 SELinux è spesso in enforcing e va trattato come parte normale del sistema, non come ostacolo accidentale. Caddy può leggere file e fare proxy, ma i permessi devono essere coerenti. Se il sito statico non serve contenuti o il proxy verso il backend fallisce, il primo sospetto non è Caddy: è il contesto SELinux o il path del file.

Controlla i denial recenti:

sudo ausearch -m AVC,USER_AVC -ts recent
sudo journalctl -t setroubleshoot --no-pager -n 50

Per contenuti statici, il path sotto `/var/www` di solito è il più lineare. Per un backend locale, il problema SELinux emerge più spesso quando un’app esterna deve scrivere log o leggere file in una directory non etichettata correttamente. In quel caso non “disabilitare SELinux”: correggi il contesto o la policy minima necessaria.

Un controllo utile sul file servito è questo:

ls -Z /var/www/example.com/html
restorecon -Rv /var/www/example.com/html

Se devi consentire a Caddy di connettersi a un backend non standard, verifica anche i boolean SELinux pertinenti solo dopo aver capito l’errore reale. Modificare i boolean “a intuito” è un modo rapido per allargare troppo la superficie d’attacco.

Log, diagnostica e lettura dei problemi più comuni

Quando qualcosa non va, la prima domanda è sempre il layer: DNS, edge, origin, app, DB o storage. Caddy mette a disposizione log di accesso e di errore; usali prima di toccare il file di configurazione. Spesso la causa è già visibile in una riga di log ben formata.

sudo journalctl -u caddy -f
sudo tail -f /var/log/caddy/access.log

Tre casi tipici:

1. 502 Bad Gateway. Il backend non risponde, ascolta sulla porta sbagliata, o rifiuta la connessione. Falsifica in pochi minuti con `curl -I http://127.0.0.1:3000` sul server stesso e con `ss -lntp | grep 3000`.

2. Errore di certificato o redirect anomalo. Spesso il DNS non punta al server giusto, oppure c’è un altro proxy davanti che altera la richiesta. Verifica con `dig +short A app.example.com` e `curl -Ik https://app.example.com`.

3. Pagina vuota o risposta parziale. Qui il problema è più spesso applicativo o di contenuto statico, non del web server. Controlla permessi file, log dell’app e, se serve, il consumo memoria con `free -h` e `top` o `systemd-cgtop`.

Certificati TLS: cosa fa Caddy e cosa devi ancora garantire tu

Caddy automatizza l’emissione e il rinnovo dei certificati, ma non elimina i prerequisiti. Il dominio deve risolvere verso il server corretto, la porta 80 deve essere raggiungibile per la validazione standard e il firewall non deve bloccare il traffico in ingresso. Se il server è dietro CDN o bilanciatore, devi capire come viene fatto il passaggio della challenge.

In ambienti con restrizioni, il problema non è “Caddy non sa fare TLS”, ma la rete che non consente la verifica dell’identità. In quel caso la soluzione cambia: DNS challenge, configurazione del provider, o esposizione temporanea della porta 80 secondo una finestra controllata.

Per confermare che il certificato sia stato emesso, controlla header e catena:

curl -Iv https://app.example.com
openssl s_client -connect app.example.com:443 -servername app.example.com < /dev/null

Se il certificato non compare o il nome non coincide, non scavare subito nella configurazione interna: prima verifica il DNS pubblico e l’eventuale presenza di record duplicati o proxy intermedi.

Hardening pratico senza complicarsi la vita

Il miglior hardening è quello che riduce le eccezioni. Caddy deve esporre solo 80 e 443, i backend devono stare su localhost o su una rete privata, e i log devono essere accessibili in modo controllato. Se possibile, limita l’accesso SSH al management network e non lasciare interfacce di amministrazione sullo stesso dominio pubblico del sito.

Se il server ospita più siti, separa i blocchi per host e usa directory distinte. Non mischiare root documentale, log e backend diversi nello stesso path “per comodità”. Quando un problema nasce, la separazione chiara dei componenti fa risparmiare ore.

Un approccio ragionevole ai log è il seguente: access log in JSON, rotazione affidata al sistema, retention secondo policy. Se devi esportarli in un SIEM, il formato strutturato è molto più utile del testo libero.

Aggiornamenti e rollback

Con un servizio esposto pubblicamente, aggiornare è parte della manutenzione normale. Prima di un upgrade, salva il `Caddyfile`, verifica la versione corrente e pianifica un rollback semplice: reinstallare la versione precedente dal repository o ripristinare il file di configurazione noto buono.

sudo cp -a /etc/caddy/Caddyfile /etc/caddy/Caddyfile.pre-upgrade.$(date +%F_%H%M%S)
sudo dnf update -y caddy
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Se dopo l’update qualcosa non torna, il rollback più rapido è ripristinare il file di configurazione e reinstallare il pacchetto precedente se il repository lo consente. Per questo conviene non cancellare mai i riferimenti di versione senza una necessità reale.

Schema operativo consigliato in produzione

La sequenza che funziona meglio è questa: installazione dal repository ufficiale, validazione del servizio, apertura selettiva del firewall, verifica SELinux, configurazione del primo host, test locale, test remoto, monitoraggio dei log. Saltare uno di questi passaggi di solito non fa guadagnare tempo: sposta solo il problema più avanti.

Se devi migrare da Nginx o Apache, tieni in parallelo il vecchio servizio finché il nuovo non risponde correttamente con DNS reale e certificato valido. Il cambio va fatto con una finestra minima e con un piano di ritorno esplicito, non con un restart sperando che tutto si sistemi da solo.

Checklist finale rapida

Prima di considerare chiusa l’installazione, verifica almeno questi punti:

  • Pacchetto installato: `caddy version` e `rpm -qi caddy` coerenti.
  • Servizio attivo: `systemctl status caddy` senza errori recenti.
  • Firewall: 80 e 443 aperte, nient’altro esposto per errore.
  • SELinux: nessun AVC recente correlato a Caddy o ai path serviti.
  • Test HTTP/HTTPS: `curl -I` e `curl -Ik` restituiscono codice atteso.
  • Rollback: backup del `Caddyfile` disponibile e testato.

Assunzione operativa: il server è un nodo Linux recente con systemd, SELinux in enforcing e traffico pubblico su 80/443; se uno di questi elementi cambia, va adattata la procedura, non forzata.