[object Object]

← back to Domain Landings

batch rollout tooling: dns_point + batch_nginx (batch 1: 18 domains live)

ee9f1e59c3915aa31b1ff73f471c25e32e86bca8 · 2026-08-17 13:14:58 -0700 · Steve Abrams

Files touched

Diff

commit ee9f1e59c3915aa31b1ff73f471c25e32e86bca8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 17 13:14:58 2026 -0700

    batch rollout tooling: dns_point + batch_nginx (batch 1: 18 domains live)
---
 batch_nginx.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/batch_nginx.sh b/batch_nginx.sh
new file mode 100644
index 0000000..5588a38
--- /dev/null
+++ b/batch_nginx.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+# Install nginx vhost + Let's Encrypt SAN cert for a batch of landing domains.
+# Usage: batch_nginx.sh <batch-id> <domain1> <domain2> ...
+# Idempotent + resilient: only certs domains that have actually propagated to this box;
+# unpropagated ones are reported so they can be retried on a re-run.
+set -u
+BATCH="$1"; shift
+DOMS="$*"
+IP="45.61.58.125"
+APP_PORT="$(cat /root/Projects/domain-landings/.port 2>/dev/null || echo 9794)"
+CONF="/etc/nginx/sites-available/dl-batch-${BATCH}.conf"
+WEBROOT="/var/www/certbot"
+
+# 1) HTTP-only block first (acme challenge + proxy) so nothing 404s during cert issuance
+{
+  echo "server {"
+  echo "    listen 80;"
+  echo "    server_name ${DOMS};"
+  echo "    location ^~ /.well-known/acme-challenge/ { root ${WEBROOT}; default_type \"text/plain\"; }"
+  echo "    location / {"
+  echo "        proxy_pass http://127.0.0.1:${APP_PORT};"
+  echo "        proxy_set_header Host \$host;"
+  echo "        proxy_set_header X-Forwarded-Host \$host;"
+  echo "        proxy_set_header X-Forwarded-Proto \$scheme;"
+  echo "    }"
+  echo "}"
+} > "$CONF"
+ln -sf "$CONF" "/etc/nginx/sites-enabled/dl-batch-${BATCH}.conf"
+nginx -t >/dev/null 2>&1 && systemctl reload nginx || { echo "NGINX_TEST_FAIL(http)"; exit 1; }
+
+# 2) keep only domains that resolve to this box (propagated) — avoids SAN-cert-wide failure
+RES=""
+for d in $DOMS; do
+  ip="$(dig +short A "$d" @1.1.1.1 2>/dev/null | tail -1)"
+  [ "$ip" = "$IP" ] && RES="$RES $d" || echo "  UNPROPAGATED $d (got '${ip:-none}')"
+done
+RES="$(echo "$RES" | xargs)"
+[ -z "$RES" ] && { echo "NO_PROPAGATED_DOMAINS"; exit 0; }
+
+# 3) SAN cert for propagated domains (apex only)
+CARGS=""; for d in $RES; do CARGS="$CARGS -d $d"; done
+certbot certonly --webroot -w "$WEBROOT" $CARGS --cert-name "dl-batch-${BATCH}" \
+  --non-interactive --agree-tos -m steve@designerwallcoverings.com --keep-until-expiring \
+  >/tmp/certbot-${BATCH}.log 2>&1
+if [ ! -f "/etc/letsencrypt/live/dl-batch-${BATCH}/fullchain.pem" ]; then
+  echo "CERT_FAILED — see tail:"; tail -6 /tmp/certbot-${BATCH}.log; exit 1
+fi
+
+# 4) final conf: 80 (acme + redirect) + 443 (proxy) for the certed domains
+{
+  echo "server {"
+  echo "    listen 80;"
+  echo "    server_name ${RES};"
+  echo "    location ^~ /.well-known/acme-challenge/ { root ${WEBROOT}; default_type \"text/plain\"; }"
+  echo "    location / { return 301 https://\$host\$request_uri; }"
+  echo "}"
+  echo "server {"
+  echo "    listen ${IP}:443 ssl http2;"
+  echo "    server_name ${RES};"
+  echo "    ssl_certificate /etc/letsencrypt/live/dl-batch-${BATCH}/fullchain.pem;"
+  echo "    ssl_certificate_key /etc/letsencrypt/live/dl-batch-${BATCH}/privkey.pem;"
+  echo "    ssl_protocols TLSv1.2 TLSv1.3;"
+  echo "    add_header X-Content-Type-Options \"nosniff\" always;"
+  echo "    location / {"
+  echo "        proxy_pass http://127.0.0.1:${APP_PORT};"
+  echo "        proxy_set_header Host \$host;"
+  echo "        proxy_set_header X-Forwarded-Host \$host;"
+  echo "        proxy_set_header X-Forwarded-Proto \$scheme;"
+  echo "    }"
+  echo "}"
+} > "$CONF"
+nginx -t >/dev/null 2>&1 && systemctl reload nginx || { echo "NGINX_TEST_FAIL(ssl)"; exit 1; }
+echo "BATCH_${BATCH}_DONE certed:$(echo $RES | wc -w)"
+echo "CERTED_LIST:${RES}"

← 90fa189 domain-landings: multi-tenant themed landing + GA4 + offer f  ·  back to Domain Landings  ·  app: admin inquiries viewer (Basic Auth, created date+time) 82ea4eb →