fleet-manager: point acme DNS-01 propagation check at a public resolver
Split-horizon DNS made lego's propagation check query the container's internal resolver, which doesn't serve the public _acme-challenge TXT record, so the challenge timed out. Add ACME_RESOLVERS (comma-separated host:port, default 8.8.8.8:53) → one --dns.resolvers flag each. Documented in .env + DEPLOY.md.
This commit is contained in:
@@ -31,6 +31,10 @@ AWS_REGION=us-east-1
|
||||
# Optional but recommended: pin the Route 53 zone. Skips ListHostedZonesByName
|
||||
# (so you can drop it from the IAM policy) and disambiguates public/private zones.
|
||||
AWS_HOSTED_ZONE_ID=
|
||||
# Public resolver(s) for the DNS-01 propagation check (comma-separated host:port).
|
||||
# Needed because internal/split-horizon DNS won't resolve the public challenge
|
||||
# record. Defaults to Google DNS; override if 8.8.8.8 is blocked (e.g. 1.1.1.1:53).
|
||||
ACME_RESOLVERS=8.8.8.8:53
|
||||
# ACME_STAGING=1 # uncomment for a dry-run vs LE staging (UNTRUSTED certs, no rate limit)
|
||||
|
||||
# --- agent plane (gRPC + mTLS, fleet CA) ---------------------------------------
|
||||
|
||||
@@ -151,6 +151,12 @@ A publicly-trusted cert also keeps the WebAuthn secure-context clean (no browser
|
||||
warnings). The side-car keeps renewing on its 12-hour loop; the manager reloads
|
||||
each new cert automatically.
|
||||
|
||||
> **Split-horizon DNS:** the side-car defaults `ACME_RESOLVERS=8.8.8.8:53` so
|
||||
> lego checks TXT propagation against **public** DNS. Without it, lego uses the
|
||||
> container's internal resolver, which doesn't serve the public
|
||||
> `_acme-challenge` record, and the challenge times out. Override if 8.8.8.8 is
|
||||
> blocked (e.g. `1.1.1.1:53`, comma-separated for several).
|
||||
|
||||
> **Origin match:** the cert CN/SAN (`FLEET_MGR_RP_ID`) must equal the origin the
|
||||
> browser uses *and* `FLEET_MGR_RP_ORIGIN` — passkeys are origin-bound. The admin
|
||||
> listener binds loopback (`127.0.0.1:9500`) by default; expose it as
|
||||
|
||||
@@ -32,6 +32,17 @@ LEGO=$(command -v lego 2>/dev/null || true)
|
||||
[ -z "$LEGO" ] && [ -x /lego ] && LEGO=/lego
|
||||
[ -z "$LEGO" ] && { echo "acme: FATAL lego binary not found (looked on PATH and /lego)"; exit 1; }
|
||||
|
||||
# Force the DNS-01 propagation check against a PUBLIC resolver — the container's
|
||||
# internal/split-horizon DNS doesn't serve the public _acme-challenge record, so
|
||||
# lego's default (system resolver) never sees the TXT and times out. Accepts a
|
||||
# comma-separated list of host:port; each becomes a --dns.resolvers flag.
|
||||
RESOLVERS=""
|
||||
if [ -n "${ACME_RESOLVERS:-}" ]; then
|
||||
OLDIFS=$IFS; IFS=','
|
||||
for r in $ACME_RESOLVERS; do RESOLVERS="$RESOLVERS --dns.resolvers $r"; done
|
||||
IFS=$OLDIFS
|
||||
fi
|
||||
|
||||
while true; do
|
||||
# First pass issues; later passes renew when near expiry.
|
||||
if [ -f "/le/certificates/$DOMAIN.crt" ]; then
|
||||
@@ -41,9 +52,9 @@ while true; do
|
||||
fi
|
||||
echo "acme: lego $* for $DOMAIN (Route 53 DNS-01)"
|
||||
|
||||
# shellcheck disable=SC2086 # $STAGING is intentionally two words when set
|
||||
# shellcheck disable=SC2086 # $STAGING/$RESOLVERS intentionally word-split
|
||||
if "$LEGO" --accept-tos --email "$EMAIL" --dns route53 --domains "$DOMAIN" \
|
||||
--path /le $STAGING "$@"; then
|
||||
--path /le $RESOLVERS $STAGING "$@"; then
|
||||
install -m 644 "/le/certificates/$DOMAIN.crt" /out/fullchain.pem
|
||||
install -m 600 "/le/certificates/$DOMAIN.key" /out/privkey.pem
|
||||
chown "$UID_OUT:$UID_OUT" /out/fullchain.pem /out/privkey.pem 2>/dev/null \
|
||||
|
||||
@@ -125,6 +125,9 @@ services:
|
||||
ACME_DOMAIN: "${FLEET_MGR_RP_ID:?set FLEET_MGR_RP_ID in .env}" # = the UI hostname
|
||||
ACME_EMAIL: "${ACME_EMAIL:?set ACME_EMAIL in .env}"
|
||||
ACME_STAGING: "${ACME_STAGING:-}" # set 1 for a dry-run
|
||||
# Public resolver(s) for the propagation check — the internal/split-horizon
|
||||
# DNS doesn't serve the public _acme-challenge record. Comma-separated host:port.
|
||||
ACME_RESOLVERS: "${ACME_RESOLVERS:-8.8.8.8:53}"
|
||||
# AWS creds for the Route 53 DNS-01 challenge (or omit + use an instance role).
|
||||
AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID:-}"
|
||||
AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY:-}"
|
||||
|
||||
Reference in New Issue
Block a user