Let the TLS bootstrap past a stale local resolver

The droplet kept a cached answer for the new hostname long after the record
was live everywhere else, and the DNS check is a courtesy — Let's Encrypt
resolves the name itself. SKIP_DNS_CHECK=1 skips it, matching the autotrader
stack's script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-08-31 13:14:42 -05:00
co-authored by Claude Opus 5
parent b820168afa
commit a55ba1ccfc
+8 -1
View File
@@ -23,6 +23,12 @@ ACME_EMAIL=$(grep -E '^ACME_EMAIL=' "$SHARED_STACK/.env" | cut -d= -f2-)
[ -n "$ACME_EMAIL" ] || fail "ACME_EMAIL is not set in $SHARED_STACK/.env" [ -n "$ACME_EMAIL" ] || fail "ACME_EMAIL is not set in $SHARED_STACK/.env"
# Let's Encrypt rate-limits failures, so check DNS before spending an attempt. # Let's Encrypt rate-limits failures, so check DNS before spending an attempt.
#
# This box's own resolver is the one thing this cannot really trust: a record
# that used to point somewhere else stays cached here long after the world can
# see the new one. SKIP_DNS_CHECK=1 is for exactly that — Let's Encrypt resolves
# the name itself anyway, so the check is a courtesy, not a gate.
if [ "${SKIP_DNS_CHECK:-0}" != "1" ]; then
log "Checking DNS" log "Checking DNS"
ip=$(curl -fsS --max-time 5 http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address 2>/dev/null \ ip=$(curl -fsS --max-time 5 http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address 2>/dev/null \
|| curl -fsS --max-time 5 https://api.ipify.org 2>/dev/null) \ || curl -fsS --max-time 5 https://api.ipify.org 2>/dev/null) \
@@ -30,7 +36,8 @@ ip=$(curl -fsS --max-time 5 http://169.254.169.254/metadata/v1/interfaces/public
got=$(getent ahostsv4 "$EXT_HOST" 2>/dev/null | awk 'NR==1{print $1}') || true got=$(getent ahostsv4 "$EXT_HOST" 2>/dev/null | awk 'NR==1{print $1}') || true
echo " droplet: $ip" echo " droplet: $ip"
echo " $EXT_HOST -> ${got:-<unresolved>}" echo " $EXT_HOST -> ${got:-<unresolved>}"
[ "$got" = "$ip" ] || fail "$EXT_HOST does not resolve to $ip — fix DNS and wait for it to propagate" [ "$got" = "$ip" ] || fail "$EXT_HOST does not resolve to $ip here — fix DNS, wait for it to propagate, or re-run with SKIP_DNS_CHECK=1 if you know this box's cache is stale"
fi
# The challenge is served over plain HTTP by the shared nginx, which needs a # The challenge is served over plain HTTP by the shared nginx, which needs a
# server block for this name before it will answer for it. # server block for this name before it will answer for it.