caddy: add caddy-dns/rfc2136 + test-rfc2136 site -- self-hosted ACME flow
Wires Caddy as the ACME client side of our new self-hosted DNS-01 flow. Proves the design end-to-end: caddy-dns/rfc2136 -> our CoreDNS rfc2136 plugin -> zone file write -> git auto-commit -> HE AXFR -> LE validates -> cert issued. Changes: - caddy/Dockerfile: --with github.com/caddy-dns/rfc2136 added alongside the existing caddy-dns/vultr. - caddy/Caddyfile: new test-rfc2136.supported.systems site that uses the new provider. server coredns:53 (docker internal), key from env, propagation_delay 60s + timeout 600s to accommodate HE pull. - docker-compose.yml: ACME_TSIG_SECRET passed to the caddy container (the same secret CoreDNS verifies on the other side of the loop). First cert issued in production: 2026-05-21 ~13:23 UTC. ~5.5 min end-to-end from Caddy starting to cert in hand. Documented in session notes; the cert sits unused in caddy-data/ until/unless something publishes ports 80/443 for that hostname.
This commit is contained in:
parent
18aa53bdc7
commit
cc33fcbcc8
@ -38,3 +38,33 @@
|
|||||||
# "Caddy is alive" sanity check inside the compose network.
|
# "Caddy is alive" sanity check inside the compose network.
|
||||||
respond "CoreDNS DoT/DoH endpoint. DoT: port 853. DoH: /dns-query" 200
|
respond "CoreDNS DoT/DoH endpoint. DoT: port 853. DoH: /dns-query" 200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ─── Test domain using caddy-dns/rfc2136 → our own CoreDNS plugin ──
|
||||||
|
#
|
||||||
|
# Proves the full self-hosted ACME DNS-01 loop end-to-end:
|
||||||
|
# 1. Caddy attempts to issue a cert for test-rfc2136.supported.systems
|
||||||
|
# 2. Caddy uses caddy-dns/rfc2136 to UPDATE _acme-challenge.<name>
|
||||||
|
# TXT record into supported.systems via our CoreDNS plugin
|
||||||
|
# 3. Plugin verifies TSIG, writes the zone file, bumps SOA
|
||||||
|
# 4. CoreDNS reloads (auto plugin, ~30s)
|
||||||
|
# 5. HE pulls the new serial within ~300s
|
||||||
|
# 6. Let's Encrypt validates from public DNS via HE
|
||||||
|
# 7. Caddy issues the cert
|
||||||
|
test-rfc2136.supported.systems {
|
||||||
|
tls {
|
||||||
|
dns rfc2136 {
|
||||||
|
key_name acme-update-key.
|
||||||
|
key_alg hmac-sha256
|
||||||
|
key {env.ACME_TSIG_SECRET}
|
||||||
|
# `coredns` resolves on the docker network to the CoreDNS
|
||||||
|
# container; port 53 is its in-container listener.
|
||||||
|
server coredns:53
|
||||||
|
}
|
||||||
|
# Use public resolvers (not docker's embedded DNS) for the
|
||||||
|
# post-update propagation check. Allow HE plenty of time to pull.
|
||||||
|
resolvers 1.1.1.1 9.9.9.9 1.0.0.1
|
||||||
|
propagation_delay 60s
|
||||||
|
propagation_timeout 600s
|
||||||
|
}
|
||||||
|
respond "test-rfc2136: cert issued via self-hosted RFC 2136 ACME flow!" 200
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,8 @@ FROM caddy:2.10.0-builder AS builder
|
|||||||
# a plugin's minimum Go version moves.
|
# a plugin's minimum Go version moves.
|
||||||
ENV GOTOOLCHAIN=auto
|
ENV GOTOOLCHAIN=auto
|
||||||
RUN xcaddy build \
|
RUN xcaddy build \
|
||||||
--with github.com/caddy-dns/vultr
|
--with github.com/caddy-dns/vultr \
|
||||||
|
--with github.com/caddy-dns/rfc2136
|
||||||
|
|
||||||
FROM caddy:2.10.0
|
FROM caddy:2.10.0
|
||||||
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
|
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
|
||||||
|
|||||||
@ -11,6 +11,9 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- CADDY_HOSTNAME=${CADDY_HOSTNAME}
|
- CADDY_HOSTNAME=${CADDY_HOSTNAME}
|
||||||
- ACME_EMAIL=${ACME_EMAIL}
|
- ACME_EMAIL=${ACME_EMAIL}
|
||||||
|
# Used by caddy-dns/rfc2136 for the test-rfc2136 site -- same
|
||||||
|
# secret CoreDNS's rfc2136 plugin verifies on the other side.
|
||||||
|
- ACME_TSIG_SECRET=${ACME_TSIG_SECRET}
|
||||||
# Optional: only required for Caddy's DNS-01 cert renewal via Vultr's
|
# Optional: only required for Caddy's DNS-01 cert renewal via Vultr's
|
||||||
# API. Cert is valid ~90 days; this env var only matters within the
|
# API. Cert is valid ~90 days; this env var only matters within the
|
||||||
# final 30d renewal window. Empty default keeps `docker compose up`
|
# final 30d renewal window. Empty default keeps `docker compose up`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user