[object Object]

← back to Coming Soon Template

add CF zone-create + GoDaddy NS-flip scripts for 21 abrams/butler domains

5341e9944a663dbd84ef08b89e8778ff0a9264dc · 2026-05-18 11:37:45 -0700 · SteveStudio2

Files touched

Diff

commit 5341e9944a663dbd84ef08b89e8778ff0a9264dc
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Mon May 18 11:37:45 2026 -0700

    add CF zone-create + GoDaddy NS-flip scripts for 21 abrams/butler domains
---
 scripts/cf_zones_create.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/godaddy_ns_flip.sh | 39 ++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/scripts/cf_zones_create.sh b/scripts/cf_zones_create.sh
new file mode 100644
index 0000000..1d8a4b7
--- /dev/null
+++ b/scripts/cf_zones_create.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+# Create Cloudflare zones for every domain in manifest.json.
+# Idempotent: if a zone already exists, reuses it. Records assigned NS + live MX.
+# Output: data/zone-setup.json  (consumed by godaddy_ns_flip.sh)
+set -uo pipefail
+
+ENV=~/Projects/secrets-manager/.env
+TOK=$(grep '^CLOUDFLARE_API_TOKEN=' "$ENV" | cut -d= -f2)
+ACCT=$(grep '^CLOUDFLARE_ACCOUNT_ID=' "$ENV" | cut -d= -f2)
+CST=~/Projects/coming-soon-template
+OUT="$CST/data/zone-setup.json"
+mkdir -p "$CST/data"
+
+domains=$(python3 -c 'import json;[print(d["domain"]) for d in json.load(open("'"$CST"'/manifest.json"))["domains"]]')
+
+echo "[" > "$OUT"
+first=1
+for d in $domains; do
+  # already a zone?
+  zr=$(curl -s "https://api.cloudflare.com/client/v4/zones?name=$d&account.id=$ACCT" \
+        -H "Authorization: Bearer $TOK")
+  zid=$(echo "$zr" | python3 -c 'import sys,json;r=json.load(sys.stdin).get("result",[]);print(r[0]["id"] if r else "")')
+
+  if [ -z "$zid" ]; then
+    cr=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones" \
+          -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
+          --data "{\"account\":{\"id\":\"$ACCT\"},\"name\":\"$d\",\"type\":\"full\"}")
+    ok=$(echo "$cr" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("success"))')
+    if [ "$ok" != "True" ]; then
+      err=$(echo "$cr" | python3 -c 'import sys,json;print("; ".join(f"{e.get(\"code\")}:{e.get(\"message\")}" for e in json.load(sys.stdin).get("errors",[])))')
+      echo "FAIL  $d  -> $err" >&2
+      [ $first -eq 0 ] && echo "," >> "$OUT"; first=0
+      python3 -c 'import json;print(json.dumps({"domain":"'"$d"'","status":"create_failed","error":"'"$err"'"}))' >> "$OUT"
+      continue
+    fi
+    zid=$(echo "$cr" | python3 -c 'import sys,json;print(json.load(sys.stdin)["result"]["id"])')
+    ns=$(echo "$cr" | python3 -c 'import sys,json;print(",".join(json.load(sys.stdin)["result"].get("name_servers",[])))')
+    state="created"
+  else
+    ns=$(echo "$zr" | python3 -c 'import sys,json;print(",".join(json.load(sys.stdin)["result"][0].get("name_servers",[])))')
+    state="already_exists"
+  fi
+
+  # live MX check (queries current authoritative DNS, pre-flip)
+  mx=$(/usr/bin/dig +short MX "$d" 2>/dev/null | head -3 | tr '\n' ';' | sed 's/;$//')
+  echo "OK    $d  [$state]  ns=$ns  mx=${mx:-none}" >&2
+
+  [ $first -eq 0 ] && echo "," >> "$OUT"; first=0
+  python3 -c 'import json,sys;print(json.dumps({"domain":"'"$d"'","status":"'"$state"'","zone_id":"'"$zid"'","cf_ns":"'"$ns"'".split(","),"live_mx":"""'"$mx"'"""}))' >> "$OUT"
+done
+echo "]" >> "$OUT"
+echo "--- wrote $OUT ---" >&2
diff --git a/scripts/godaddy_ns_flip.sh b/scripts/godaddy_ns_flip.sh
new file mode 100755
index 0000000..f0663bd
--- /dev/null
+++ b/scripts/godaddy_ns_flip.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+# Flip GoDaddy nameservers to the Cloudflare-assigned pair for each domain.
+# Reads data/zone-setup.json (produced by cf_zones_create.sh).
+# SAFETY: any domain with live MX records is HELD BACK, not flipped.
+# Dry-run by default; pass --apply to actually PATCH GoDaddy.
+set -uo pipefail
+
+ENV=~/Projects/secrets-manager/.env
+KEY=$(grep '^GODADDY_API_KEY=' "$ENV" | cut -d= -f2)
+SEC=$(grep '^GODADDY_API_SECRET=' "$ENV" | cut -d= -f2)
+CST=~/Projects/coming-soon-template
+IN="$CST/data/zone-setup.json"
+APPLY=0; [ "${1:-}" = "--apply" ] && APPLY=1
+
+[ -f "$IN" ] || { echo "missing $IN — run cf_zones_create.sh first" >&2; exit 1; }
+echo "mode: $([ $APPLY -eq 1 ] && echo APPLY || echo DRY-RUN)"
+
+python3 -c 'import json;[print(z["domain"]+"\t"+",".join(z.get("cf_ns",[]))+"\t"+(z.get("live_mx") or "")) for z in json.load(open("'"$IN"'")) if z.get("status") in ("created","already_exists")]' \
+| while IFS=$'\t' read -r d ns mx; do
+  if [ -n "$mx" ]; then
+    echo "HOLD  $d  — live MX present ($mx); not flipping"
+    continue
+  fi
+  if [ -z "$ns" ]; then echo "SKIP  $d  — no CF nameservers recorded"; continue; fi
+  body=$(python3 -c 'import json,sys;print(json.dumps({"nameServers":sys.argv[1].split(",")}))' "$ns")
+  if [ $APPLY -eq 1 ]; then
+    code=$(curl -s -o /tmp/gd_resp -w '%{http_code}' -X PATCH \
+      "https://api.godaddy.com/v1/domains/$d" \
+      -H "Authorization: sso-key $KEY:$SEC" -H "Content-Type: application/json" \
+      --data "$body")
+    if [ "$code" = "200" ] || [ "$code" = "204" ]; then
+      echo "FLIP  $d  -> $ns  [HTTP $code]"
+    else
+      echo "FAIL  $d  [HTTP $code]  $(cat /tmp/gd_resp)"
+    fi
+  else
+    echo "WOULD-FLIP  $d  -> $ns"
+  fi
+done

← 67ff39c Add Cloudflare Pages deploy script — artifact-dir only, neve  ·  back to Coming Soon Template  ·  rewrite CF zone setup in Node — real error capture (token la 78446c1 →