← back to Homesonspec
finish-tk10.sh
191 lines
#!/usr/bin/env bash
# ============================================================================
# finish-tk10.sh — one-command HomesOnSpec.com production go-live finisher
# ============================================================================
# TK-10 turnkey driver. Steve does exactly ONE manual thing first (the GoDaddy
# nameserver swap — GoDaddy's write-API is 404-gated for this domain, so it
# CANNOT be automated), then runs this ONE script to finish the go-live.
#
# DO THIS ONE THING FIRST (GoDaddy dashboard, homesonspec.com → Nameservers):
# change from ns69.domaincontrol.com + ns70.domaincontrol.com
# to ezra.ns.cloudflare.com + kimora.ns.cloudflare.com
# THEN run: bash ~/Projects/homesonspec/finish-tk10.sh
#
# WHAT THIS SCRIPT DOES (in order):
# (a) GATE — verifies `dig NS homesonspec.com` actually shows the two
# Cloudflare nameservers. If not (swap not done / not propagated yet),
# it PRINTS the exact GoDaddy step and EXITS 2. Nothing else runs.
# (b) CLOUDFLARE — runs cutover-dns.sh (API-driven + reversible) to ensure
# the CF zone / proxied A / email records / SSL=full are all in place.
# (Idempotent — a no-op if everything is already set.)
# (c) DEPLOY + SMOKE — runs the project's deploy script (Kamatera) and then
# HTTP-smoke-tests the apex + admin.
# (d) REVOKE — PRINTS (does NOT auto-run) the exact old-GoDaddy-key
# revocation step for Steve to do by hand.
#
# ── REQUIREMENTS ────────────────────────────────────────────────────────────
# * The DEPLOY step (c) SSHes to Kamatera (root@45.61.58.125). Run this from
# a Kamatera-SSH-CAPABLE session (a plain interactive shell on Mac2 — NOT a
# sandboxed agent/workflow session, whose SSH is blocked). If SSH is not
# available, pass --skip-deploy to run only the Cloudflare + gate steps and
# deploy by hand.
# * Reads Cloudflare + GoDaddy creds from ~/Projects/secrets-manager/.env
# (the same source cutover-dns.sh uses). No secrets live in this file.
#
# ── PATH NOTE (pre-existing) ────────────────────────────────────────────────
# The gitignored deploy scripts (deploy-kamatera.sh / golive-homesonspec.sh)
# still reference the OLD source path `~/Projects/spechomes` and remote
# `/root/Projects/spechomes` internally (project was renamed to homesonspec).
# That is intentional-for-now: the Kamatera remote dir is still
# /root/Projects/spechomes and the local rsync source `~/Projects/spechomes`
# must exist for deploy-kamatera.sh. This driver runs the scripts AS-IS from
# ~/Projects/homesonspec (where they physically live). If ~/Projects/spechomes
# no longer exists, choose --relaunch (golive-homesonspec.sh, which also uses
# the spechomes source path) or fix the paths in the deploy script first.
#
# ── FLAGS ───────────────────────────────────────────────────────────────────
# --relaunch use golive-homesonspec.sh (demo-purge relaunch on an
# already-seeded prod DB) instead of deploy-kamatera.sh
# (first-time full stand-up). Default: first-time stand-up.
# --skip-deploy run gate + Cloudflare + revoke-notice only; skip step (c).
# --skip-cf skip step (b) (assume CF already fully cut over).
# -h | --help show this header.
# ============================================================================
set -euo pipefail
DOMAIN=homesonspec.com
ORIGIN_IP=45.61.58.125
WEB_PORT=9975
ADMIN_PORT=9976
CF_NS1=ezra.ns.cloudflare.com
CF_NS2=kimora.ns.cloudflare.com
PROJ_DIR="$HOME/Projects/homesonspec"
CUTOVER="$PROJ_DIR/cutover-dns.sh"
DEPLOY="$PROJ_DIR/deploy-kamatera.sh"
RELAUNCH_SCRIPT="$PROJ_DIR/golive-homesonspec.sh"
RELAUNCH=0
SKIP_DEPLOY=0
SKIP_CF=0
for arg in "$@"; do
case "$arg" in
--relaunch) RELAUNCH=1 ;;
--skip-deploy) SKIP_DEPLOY=1 ;;
--skip-cf) SKIP_CF=1 ;;
-h|--help) sed -n '2,60p' "$0"; exit 0 ;;
*) echo "unknown flag: $arg (see --help)"; exit 64 ;;
esac
done
hr() { printf '────────────────────────────────────────────────────────────\n'; }
say() { printf '\n\033[1m%s\033[0m\n' "$*"; }
# ── (a) GATE on nameserver propagation ──────────────────────────────────────
say "(a) GATE — checking homesonspec.com nameservers"
hr
CUR_NS=$(dig +short NS "$DOMAIN" | sed 's/\.$//' | sort | tr '\n' ' ' | sed 's/ *$//')
echo " dig NS $DOMAIN → ${CUR_NS:-<empty>}"
if echo "$CUR_NS" | grep -qi "$CF_NS1" && echo "$CUR_NS" | grep -qi "$CF_NS2"; then
echo " ✓ Cloudflare nameservers are live — the GoDaddy swap is done. Continuing."
else
cat <<GATE
✗ NOT YET on Cloudflare — the go-live is blocked on ONE manual step.
┌──────────────────────────────────────────────────────────────────┐
│ DO THIS ONE THING (GoDaddy dashboard): │
│ │
│ homesonspec.com → Nameservers → Change → Enter my own │
│ set: $CF_NS1
│ $CF_NS2
│ (was: ns69.domaincontrol.com + ns70.domaincontrol.com) │
│ │
│ Then re-run: bash ~/Projects/homesonspec/finish-tk10.sh │
└──────────────────────────────────────────────────────────────────┘
(GoDaddy's NS-swap write API returns 404 for this domain, so this step
cannot be automated. Propagation after you save takes ~5–30 min — if the
dashboard already shows the CF nameservers, just wait a few minutes and
re-run this script.)
GATE
exit 2
fi
# ── (b) CLOUDFLARE half (API-driven, reversible, idempotent) ────────────────
if [ "$SKIP_CF" -eq 1 ]; then
say "(b) CLOUDFLARE — skipped (--skip-cf)"
else
say "(b) CLOUDFLARE — ensuring zone / proxied A / email / SSL (cutover-dns.sh)"
hr
if [ ! -f "$CUTOVER" ]; then
echo " ✗ $CUTOVER not found — cannot run the Cloudflare half. ABORT."; exit 1
fi
# cutover-dns.sh is idempotent: upserts records, sets SSL=full/always_use_https,
# re-writes ROLLBACK-DNS.txt, and (harmlessly) no-ops on the 404-gated GoDaddy PUT.
bash "$CUTOVER" || {
echo " ⚠ cutover-dns.sh returned non-zero (the 404-gated GoDaddy NS PUT is expected"
echo " to fail; the Cloudflare record/SSL upserts above it are what matter). Review"
echo " the output above — if only the GoDaddy PUT failed, this is fine."; }
fi
# ── (c) DEPLOY + smoke test ─────────────────────────────────────────────────
if [ "$SKIP_DEPLOY" -eq 1 ]; then
say "(c) DEPLOY — skipped (--skip-deploy)"
else
if [ "$RELAUNCH" -eq 1 ]; then
DEPLOY_SCRIPT="$RELAUNCH_SCRIPT"; DEPLOY_KIND="re-launch (demo-purge on seeded prod DB)"
else
DEPLOY_SCRIPT="$DEPLOY"; DEPLOY_KIND="first-time full stand-up"
fi
say "(c) DEPLOY — $DEPLOY_KIND → Kamatera ($ORIGIN_IP)"
hr
if [ ! -f "$DEPLOY_SCRIPT" ]; then
echo " ✗ $DEPLOY_SCRIPT not found. ABORT."; exit 1
fi
echo " running: bash $DEPLOY_SCRIPT"
echo " (SSHes to root@$ORIGIN_IP — requires a Kamatera-SSH-capable session)"
bash "$DEPLOY_SCRIPT"
say " smoke test"
hr
# Apex through Cloudflare edge (proxied). Allow a few tries for edge warm-up.
APEX=000
for i in 1 2 3 4 5; do
APEX=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "https://$DOMAIN/" || echo 000)
[ "$APEX" = "200" ] && break
echo " apex try $i → $APEX (retrying in 5s)"; sleep 5
done
echo -n " apex https://$DOMAIN/ → $APEX"; [ "$APEX" = "200" ] && echo " ✓" || echo " ✗ (edge/cert may still be warming — recheck in a few min)"
# Admin should fail closed (401) unauthenticated. Admin is origin-only (not in
# public DNS), so probe the origin directly via the Host header.
ADMINCODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "http://$ORIGIN_IP:$ADMIN_PORT/" || echo 000)
echo -n " admin origin :$ADMIN_PORT (401 expected, fails closed) → $ADMINCODE"
[ "$ADMINCODE" = "401" ] && echo " ✓" || echo " — (verify: unauthenticated admin must be 401)"
fi
# ── (d) REVOKE the old GoDaddy key (PRINT ONLY — Steve runs this by hand) ────
say "(d) FINAL MANUAL STEP — revoke the old GoDaddy sso-key"
hr
cat <<'REVOKE'
The leaked-then-scrubbed GoDaddy sso-key is git-clean but STILL LIVE at
GoDaddy until you revoke it. Every live consumer already prefers the new
Bearer PAT (verified under TK-10), so revoking is safe.
DO THIS (by hand — NOT automated):
1. Go to https://developer.godaddy.com/keys
2. REVOKE the old key (fleet-wide key, sha-prefix 96974d0c).
3. If you also created a fresh key, run: /secrets
to fan it across all .env / MCP / skill envs.
4. Delete the pre-scrub backup that still holds old secrets:
rm -rf ~/Projects/spechomes.pre-scrub-backup
ROLLBACK (if the launch needs undoing):
GoDaddy dashboard → homesonspec.com → Nameservers → set back to
ns69.domaincontrol.com + ns70.domaincontrol.com (manual — the API PUT is
404-gated). If a demo-purge relaunch ran, restore the pg_dump the
golive script printed.
REVOKE
say "✅ finish-tk10.sh complete — homesonspec.com is live once the smoke checks are green."