Salta al contenuto
AImpact
IT EN
Infrastruttura AI 6 min di lettura

Caddy come reverse proxy: più semplice di Nginx, HTTPS automatico

Come sostituire Nginx con Caddy per esporre servizi self-hosted con HTTPS automatico e configurazione in 10 righe. Guida pratica con Docker Compose.

Pubblicato: 3 giugno 2025

Nginx è ottimo, ma ogni volta che aggiungi un servizio devi scrivere un blocco di configurazione, ricordarti di ricaricare certbot, rinnovare il certificato manualmente se qualcosa va storto. Caddy risolve tutto questo per default: HTTPS con Let’s Encrypt è automatico, il Caddyfile è leggibile, e bastano davvero 10 righe per esporre tre servizi su domini diversi.

Perché Caddy invece di Nginx

Nginx ha una configurazione verbosa e il TLS richiede certbot come processo separato con cron job di rinnovo. Caddy gestisce tutto internamente: ottiene il certificato al primo avvio, lo rinnova da solo, e se il dominio non è ancora propagato riprova in background senza crashare.

Per un server self-hosted con 5-10 servizi, Caddy riduce la configurazione da 150 righe a 30. Non è una questione di prestazioni — Nginx e Caddy sono equivalenti su traffico normale — è una questione di manutenzione.

Caddyfile base

Un Caddyfile che espone tre servizi locali su HTTPS:

app.example.com {
    reverse_proxy localhost:3000
}

api.example.com {
    reverse_proxy localhost:8000
}

monitor.example.com {
    reverse_proxy localhost:9000
}

Questo è tutto. Caddy contatta Let’s Encrypt, ottiene tre certificati, li rinnova automaticamente. Non tocchi più niente.

Docker Compose con Caddy come gateway

Nella pratica, i tuoi servizi girano già in container. Ecco un docker-compose.yml completo con Caddy davanti a due servizi:

services:
  caddy:
    image: caddy:2-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - proxy

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    networks:
      - proxy

  portainer:
    image: portainer/portainer-ce:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - proxy

networks:
  proxy:

volumes:
  caddy_data:
  caddy_config:

Il Caddyfile corrispondente usa i nomi dei servizi Docker come hostname (Caddy e i container sono sulla stessa network):

chat.example.com {
    reverse_proxy open-webui:8080
}

portainer.example.com {
    reverse_proxy portainer:9000
}

Wildcard certificate con Cloudflare

Se vuoi un singolo certificato wildcard per *.example.com invece di uno per dominio, devi fare il DNS challenge. Funziona solo se il tuo DNS è su Cloudflare (o altro provider supportato).

Usa l’immagine caddy:2-builder per compilare Caddy con il plugin DNS:

FROM caddy:2-builder AS builder
RUN xcaddy build --with github.com/caddy-dns/cloudflare

FROM caddy:2-alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Nel Caddyfile:

*.example.com {
    tls {
        dns cloudflare {env.CF_API_TOKEN}
    }
    @webui host chat.example.com
    handle @webui {
        reverse_proxy open-webui:8080
    }
}

Passa il token Cloudflare come variabile d’ambiente nel docker-compose.yml. Non serve aprire la porta 80 per il DNS challenge.

Cosa fare

  • Installa Caddy con docker compose up -d, punta un sottodominio al tuo IP e guarda i log con docker compose logs caddy per vedere il certificato emesso in tempo reale
  • Migra da Nginx un servizio alla volta: metti Caddy in ascolto su una porta alternativa (ad es. 8443) per testare prima di spostare il traffico principale
  • Se usi Cloudflare, attiva il DNS challenge e consolida tutto sotto un wildcard *.tuodominio.com per evitare di gestire certificati singoli per ogni nuovo servizio