# Caddy is used here purely as an ACME client + cert renewer for CoreDNS. # The HTTPS site is technically served (Caddy can't issue without a site # block), but we don't expose port 443 from this container — only the # cert files in /data/caddy/ are consumed by the CoreDNS sidecar. { # Operator contact for Let's Encrypt; also used for expiry warnings. email {$ACME_EMAIL} # Skip the HTTP-to-HTTPS redirect server (we have nothing to redirect). # Caddy still binds :443 inside the container for the cert site, which # is fine because we don't publish those ports to the host. auto_https disable_redirects } {$CADDY_HOSTNAME} { tls { # DNS-01 challenge via Vultr API. The plugin reads the token from # the named env var; setting via {env.VULTR_API_KEY} would also # work but the bare reference is clearer with Caddy's modules. dns vultr {env.VULTR_API_KEY} # Use PUBLIC resolvers for the propagation check, not Docker's # embedded DNS. Without this, Caddy follows the container's # resolv.conf → host's resolv.conf → local LAN resolvers, which # on a split-horizon DNS setup will return LAN IPs for vultr.com # nameservers and the propagation check fails with connection # refused. Hitting 1.1.1.1 / 9.9.9.9 directly sidesteps it. resolvers 1.1.1.1 9.9.9.9 1.0.0.1 # Vultr's NS propagation is generally fast (<30s) but LE checks # multiple resolvers; cushion the wait to avoid flaky issuance. propagation_delay 30s propagation_timeout 300s } # A sensible response if anyone hits this on 443. Doubles as a # "Caddy is alive" sanity check inside the compose network. respond "CoreDNS DoT/DoH endpoint. DoT: port 853. DoH: /dns-query" 200 }