fix: Caddy TLS cert acquisition — two DNS-01 blockers
Unit Tests / test (push) Successful in 7m32s

1. caddy_manager: embed ddns.token (registration bearer token) in
   Caddyfile, not DDNS_TOTP_SECRET. The pic_ngo plugin sends the token
   to POST /api/v1/dns-challenge; using the TOTP secret caused 401 on
   every attempt.

2. firewall_manager: add _acme-challenge.<zone> forwarding block before
   each split-horizon zone in the Corefile. Without this, CoreDNS was
   authoritative for the challenge name and returned NODATA for TXT
   queries (wildcard A record matches but wrong type), blocking Caddy's
   internal DNS pre-verification step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 10:45:15 -04:00
parent 76bbc2b67a
commit 85d265187d
4 changed files with 36 additions and 15 deletions
+12
View File
@@ -758,6 +758,18 @@ def generate_corefile(peers: List[Dict[str, Any]], corefile_path: str = COREFILE
# *.pic1.pic.ngo to the internal Caddy IP without hairpin NAT.
if split_horizon_zones:
for sz in split_horizon_zones:
# More-specific block for ACME DNS-01 challenge records: forward
# to public DNS so Caddy can verify TXT records it creates on the
# DDNS server. Without this, the wildcard A record in the zone
# file causes CoreDNS to return NODATA for TXT queries, blocking
# Caddy's internal pre-verification step.
corefile += (
f'\n_acme-challenge.{sz} {{\n'
f' forward . 8.8.8.8 1.1.1.1\n'
f' cache\n'
f' log\n'
f'}}\n'
)
corefile += (
f'\n{sz} {{\n'
f' file /data/{sz}.zone\n'