NoctisNode
← GuideSicurezza2026-10-2310 min

HTTPS automatico con Caddy: come funziona l'auto TLS e come risolvere i problemi

Caddy ottiene e rinnova i certificati TLS via ACME per ogni dominio della configurazione. Scopri HTTP-01, TLS-ALPN-01, wildcard con DNS-01, on-demand TLS e gli errori più comuni.

In breve: Caddy attiva l'HTTPS automaticamente per qualsiasi indirizzo di sito che sia un nome di dominio pubblico. Richiede un certificato via ACME (Let's Encrypt o ZeroSSL per impostazione predefinita), dimostra il controllo del dominio con la challenge HTTP-01 o TLS-ALPN-01 sulle porte 80 e 443, reindirizza l'HTTP verso l'HTTPS e rinnova il certificato prima della scadenza, senza alcuna configurazione aggiuntiva.

Un reverse proxy Caddy è semplicemente Caddy che termina quella connessione HTTPS e inoltra la richiesta a un'app su un'altra porta, container o host tramite la direttiva `reverse_proxy`. Questa combinazione, TLS più proxy in poche righe, è il motivo principale per cui viene scelto.

Reverse proxy con SSL in tre righe

Con il DNS che punta al server e le porte 80 e 443 raggiungibili, questo Caddyfile è un reverse proxy HTTPS completo per due hostname. All'avvio Caddy ottiene i certificati per entrambi i nomi, serve HTTP/1.1, HTTP/2 e HTTP/3 e passa al backend `X-Forwarded-For`, `X-Forwarded-Proto` e `X-Forwarded-Host`. L'opzione `email` è facoltativa, ma permette alla CA di contattarti per certificati in scadenza o revocati.

L'installazione dal repository apt ufficiale e le basi di systemd sono trattate nella guida al reverse proxy con Caddy; per i container vedi Caddy come reverse proxy Docker. Applica le modifiche con `sudo systemctl reload caddy`.

# /etc/caddy/Caddyfile
{
	email [email protected]
}

example.com, www.example.com {
	reverse_proxy 127.0.0.1:8080
}

Come funziona l'auto TLS di Caddy dietro le quinte

Quando Caddy carica una configurazione, raccoglie tutti gli hostname dagli indirizzi dei siti e decide chi deve emettere ciascun certificato. I domini pubblici vanno agli issuer ACME pubblici; `localhost`, gli indirizzi IP e i nomi solo interni ricevono certificati dalla CA locale di Caddy (equivale a scrivere `tls internal`). Certificati, chiavi e account ACME sono salvati nella directory dati di Caddy: `/var/lib/caddy/.local/share/caddy` per il pacchetto apt, `/data` nell'immagine Docker ufficiale.

Il rinnovo avviene in background con largo anticipo sulla scadenza, e Caddy fa lo stapling delle risposte OCSP dove la CA lo supporta. Se l'emissione fallisce, Caddy riprova con backoff esponenziale e usa l'endpoint di staging della CA per i tentativi successivi, per non consumare i rate limit di produzione. Più istanze di Caddy che condividono lo stesso storage si coordinano in modo che solo una richieda un dato certificato.

ChallengeCosa verifica la CARequisitiWildcard?
HTTP-01Un token servito su `http://domain/.well-known/acme-challenge/`Porta 80 raggiungibile da internetNo
TLS-ALPN-01Un certificato speciale presentato durante un handshake TLSPorta 443 raggiungibile da internetNo
DNS-01Un record TXT su `_acme-challenge.domain`Token API del provider DNS e una build di Caddy con il modulo di quel providerSì

Certificati wildcard con DNS-01

I certificati wildcard come `*.example.com` possono essere emessi solo tramite la challenge DNS-01. Il binario standard di Caddy non include i plugin dei provider DNS, quindi ne compili uno con xcaddy (o scegli il provider nella pagina di download ufficiale) e fornisci a Caddy un token API limitato alla modifica del DNS di quella zona. DNS-01 funziona anche quando le porte 80 e 443 non sono raggiungibili da internet, per esempio su un server solo interno.

Tieni il token fuori dal Caddyfile: mettilo in un file di ambiente usato dall'unit systemd (`sudo systemctl edit caddy`, poi `EnvironmentFile=/etc/caddy/caddy.env` sotto `[Service]`) e limita i permessi del file con `chmod 600`.

# Build Caddy with a DNS provider module (example: Cloudflare)
xcaddy build --with github.com/caddy-dns/cloudflare

# Caddyfile: one wildcard certificate for all subdomains
*.example.com {
	tls {
		dns cloudflare {env.CF_API_TOKEN}
	}

	@app host app.example.com
	handle @app {
		reverse_proxy 127.0.0.1:3000
	}

	handle {
		respond "Unknown host" 404
	}
}

On-demand TLS e staging

L'on-demand TLS fa sì che Caddy ottenga un certificato durante il primo handshake TLS per un hostname mai visto prima. È pensato per piattaforme in cui i clienti puntano i propri domini al tuo server. Configura sempre l'endpoint `ask`: Caddy lo chiama con `?domain=name` e procede solo con una risposta 200. Senza di esso, chiunque potrebbe puntare nomi a caso al tuo IP e farti raggiungere i rate limit.

Mentre sperimenti, passa alla CA di staging di Let's Encrypt con l'opzione globale `acme_ca`. I certificati di staging non sono considerati attendibili dai browser, ma i limiti sono molto più alti, quindi puoi rompere e sistemare le cose liberamente. Quando hai finito, rimuovi l'opzione ed eventualmente elimina i certificati di staging dalla directory dati.

{
	on_demand_tls {
		ask http://127.0.0.1:5555/allowed
	}
}

https:// {
	tls {
		on_demand
	}
	reverse_proxy 127.0.0.1:8080
}

# Global options block for testing
{
	email [email protected]
	# Test against Let's Encrypt staging; remove when everything works
	acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

Errori TLS comuni di Caddy e come risolverli

  1. 01.DNS non puntato: il record A o AAAA manca, punta ancora a un vecchio server o è in cache. Un record AAAA obsoleto è una trappola classica, perché la CA preferisce IPv6 quando esiste. Controllali entrambi con `dig`.
  2. 02.Porta 80 o 443 chiusa: il firewall dell'host, un firewall cloud o un router blocca il traffico in ingresso, quindi né HTTP-01 né TLS-ALPN-01 possono completarsi. Apri 80/tcp e 443/tcp (e 443/udp per HTTP/3).
  3. 03.Porta già in uso: Apache, nginx o un altro container è in ascolto su 80 o 443, quindi Caddy non può mettersi in ascolto. Ferma l'altro servizio o spostalo dietro Caddy.
  4. 04.Proxy CDN davanti: un proxy in stile «nuvola arancione» termina il TLS prima di Caddy, e questo può rompere TLS-ALPN-01. Usa DNS-01, oppure imposta il record come solo DNS durante l'emissione.
  5. 05.Rate limit: tentativi falliti ripetuti o la cancellazione della directory dati ti fanno raggiungere i limiti della CA (Let's Encrypt limita le validazioni fallite per hostname all'ora e i certificati duplicati a settimana). Risolvi la causa, usa lo staging e mantieni persistente la directory dati.
  6. 06.Record CAA: un record CAA che autorizza solo una CA diversa blocca l'emissione. Autorizza `letsencrypt.org` e `sectigo.com` (usato da ZeroSSL) oppure rimuovi la restrizione.
# Does the name resolve to this server (both IPv4 and IPv6)?
dig +short A example.com
dig +short AAAA example.com
curl -4 -s https://ifconfig.me ; echo

# Are ports 80 and 443 open in the host firewall?
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp

# Is something else already bound to 80/443?
sudo ss -ltnp '( sport = :80 or sport = :443 )'

# What does Caddy say?
sudo journalctl -u caddy --no-pager -n 100

HTTPS anche verso il backend

La maggior parte dei backend sullo stesso host parla HTTP in chiaro su localhost, e va bene così. Quando l'upstream è su un'altra macchina o richiede TLS, usa un upstream `https://` e indica a Caddy quale nome verificare e di quale CA fidarsi. Evita `tls_insecure_skip_verify` al di fuori di test veloci, perché elimina la protezione contro l'intercettazione tra proxy e backend. Per il traffico tra server, un tunnel WireGuard privato è spesso più semplice che gestire i certificati dei backend.

Su un VPS NoctisNode con root completo e un indirizzo IPv4 dedicato, la configurazione tipica è: punta un record A (nessun AAAA a meno che il server non abbia IPv6) al server, apri 80 e 443 e lascia che Caddy faccia il resto. Se devi inoltrare traffico non HTTP, vedi proxy TCP e SSH con Caddy.

example.com {
	reverse_proxy https://10.0.0.5:8443 {
		transport http {
			tls_server_name backend.internal
			tls_trust_pool file /etc/caddy/backend-ca.pem
		}
	}
}

FAQ

QCos'è un reverse proxy Caddy?

AÈ il web server Caddy che accetta le connessioni dei client, di solito terminando l'HTTPS, e inoltra le richieste a uno o più servizi backend con la direttiva `reverse_proxy`. Caddy ottiene e rinnova automaticamente i relativi certificati TLS.

QCaddy rinnova i certificati automaticamente?

ASì. Caddy rinnova i certificati in background con largo anticipo sulla scadenza e li ricarica senza riavvio, purché il dominio risolva ancora verso il server e le porte delle challenge restino raggiungibili.

QPerché Caddy non ottiene un certificato?

ALe cause più comuni sono record DNS che puntano altrove (incluso un record AAAA obsoleto), porte 80 e 443 bloccate, un altro programma che usa quelle porte o rate limit dopo fallimenti ripetuti. `journalctl -u caddy` mostra l'errore ACME esatto.

QCaddy può emettere un certificato wildcard?

ASì, ma solo tramite la challenge DNS-01, che richiede una build di Caddy con il modulo del tuo provider DNS e un token API per quella zona.

QCome disattivo l'HTTPS automatico in Caddy?

AUsa un indirizzo di sito `http://` per un singolo sito, oppure imposta l'opzione globale `auto_https off`. Puoi anche usare `auto_https disable_redirects` per mantenere i certificati ma fermare il redirect da HTTP a HTTPS.

HTTPS automatico con Caddy: come funziona l'auto TLS e come risolvere i problemi · NoctisNode