[object Object]

← back to Gallery Agentabrams

deploy: make deploy.sh idempotent + SSL-safe (installs HTTPS vhost when cert exists; never regresses SSL on re-run)

49e3ef93e16eeed847c2fa2a7019e7180a987293 · 2026-09-01 10:15:48 -0700 · Steve Abrams

Files touched

Diff

commit 49e3ef93e16eeed847c2fa2a7019e7180a987293
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Sep 1 10:15:48 2026 -0700

    deploy: make deploy.sh idempotent + SSL-safe (installs HTTPS vhost when cert exists; never regresses SSL on re-run)
---
 deploy/deploy.sh | 37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/deploy/deploy.sh b/deploy/deploy.sh
index 7a154df..ae08984 100755
--- a/deploy/deploy.sh
+++ b/deploy/deploy.sh
@@ -1,13 +1,14 @@
 #!/bin/bash
-# gallery.agentabrams.com — full first deploy (DNS + rsync + nginx + SSL).
-# STEVE-GATED: this creates a Cloudflare DNS record and publishes a public site.
-# Run only with explicit approval.
+# gallery.agentabrams.com — idempotent deploy (DNS + rsync + nginx + SSL).
+# STEVE-GATED: touches Cloudflare DNS + a public Kamatera site. Explicit approval only.
+# Safe to re-run: mirrors content and KEEPS SSL once the cert exists (never
+# regresses HTTPS). First run on a fresh domain bootstraps HTTP -> webroot cert -> SSL.
 set -euo pipefail
 KAMATERA=root@45.61.58.125
 SITE=gallery.agentabrams.com
 HERE="$(cd "$(dirname "$0")/.." && pwd)"
 
-# 1. DNS: A record gallery -> Kamatera (DNS-only, matches fleet pattern)
+# 1. DNS: ensure A record gallery -> Kamatera (DNS-only, fleet pattern)
 export $(grep -E "^CLOUDFLARE_API_TOKEN=" ~/Projects/secrets-manager/.env)
 ZONE=$(curl -s -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
   "https://api.cloudflare.com/client/v4/zones?name=agentabrams.com" \
@@ -28,19 +29,23 @@ fi
 rsync -az --delete --exclude .git --exclude deploy --exclude README.md "$HERE/" $KAMATERA:/var/www/$SITE/
 echo "content rsynced (mirrored)"
 
-# 3. nginx (80 first so certbot HTTP-01 can pass)
-scp -q "$HERE/deploy/$SITE.nginx" $KAMATERA:/etc/nginx/sites-available/$SITE
-ssh $KAMATERA "ln -sf /etc/nginx/sites-available/$SITE /etc/nginx/sites-enabled/$SITE && nginx -t && systemctl reload nginx"
-echo "nginx staged"
-
-# 4. Wait for DNS, then SSL
-for i in $(seq 1 30); do
-  [ -n "$(dig +short $SITE @1.1.1.1)" ] && break
-  sleep 10
-done
-ssh $KAMATERA "certbot --nginx -d $SITE --non-interactive --agree-tos -m steve@designerwallcoverings.com && systemctl reload nginx"
+# 3. nginx — install the RIGHT vhost for the current cert state (SSL-safe)
+CERT="/etc/letsencrypt/live/$SITE/fullchain.pem"
+if ssh $KAMATERA "test -f $CERT"; then
+  echo "cert present -> installing SSL vhost (keeping HTTPS)"
+  scp -q "$HERE/deploy/$SITE.ssl.nginx" $KAMATERA:/etc/nginx/sites-available/$SITE
+  ssh $KAMATERA "ln -sf /etc/nginx/sites-available/$SITE /etc/nginx/sites-enabled/$SITE && nginx -t && systemctl reload nginx"
+else
+  echo "no cert yet -> HTTP bootstrap + webroot issuance"
+  scp -q "$HERE/deploy/$SITE.nginx" $KAMATERA:/etc/nginx/sites-available/$SITE
+  ssh $KAMATERA "ln -sf /etc/nginx/sites-available/$SITE /etc/nginx/sites-enabled/$SITE && nginx -t && systemctl reload nginx"
+  for i in $(seq 1 30); do [ -n "$(dig +short $SITE @1.1.1.1)" ] && break; sleep 10; done
+  ssh $KAMATERA "certbot certonly --webroot -w /var/www/$SITE -d $SITE --non-interactive --agree-tos -m steve@designerwallcoverings.com"
+  scp -q "$HERE/deploy/$SITE.ssl.nginx" $KAMATERA:/etc/nginx/sites-available/$SITE
+  ssh $KAMATERA "nginx -t && systemctl reload nginx"
+fi
 
-# 5. Smoke test
+# 4. Smoke test
 sleep 2
 code=$(curl -s -o /dev/null -w '%{http_code}' https://$SITE/)
 echo "https://$SITE -> HTTP $code"

← 11ef5ba deploy: webroot SSL issuance script + HTTPS vhost (nginx-plu  ·  back to Gallery Agentabrams  ·  add Grateful Dead collection to build gallery 797d116 →