From 1cd1d3bbbaf911831b5b2202d9567cf2fe2e6ef5 Mon Sep 17 00:00:00 2001
From: karti-ai <176560021+karti-ai@users.noreply.github.com>
Date: Fri, 28 Aug 2026 17:06:30 -0700
Subject: [PATCH] Serve the site under demo.lumbridgecorp.com as well
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
One Caddy block, both names, same root. The prerendered HTML already carries
and og:url pointing at the primeintellectgrowth name on
every route, so the alias does not split search ranking or leave a shared link
ambiguous about which site it belongs to. Verified byte-identical: both
hostnames return the same sha256 for /demos/wordle.
Worth recording why the alias failed before this rather than 404ing.
lumbridgecorp.com resolves on a WILDCARD, so every subdomain of it points at
cloud-2 whether or not Caddy knows the name. DNS completes, TLS opens, Caddy
finds no certificate for that SNI and aborts the handshake — the browser reports
ERR_SSL_PROTOCOL_ERROR, which reads as "the site is down" rather than "wrong
hostname". primeintellectgrowth.com has no wildcard, which is why the canonical
name needed an explicit A record.
deploy.sh now smoke-tests the alias too: if the block is ever edited to drop the
second name, the failure mode is a TLS error, and nothing else would catch it.
The live block is mirrored into deploy/Caddyfile.demo so the config is
reviewable in the repo rather than only on the host.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
---
deploy/Caddyfile.demo | 37 +++++++++++++++++++++++++++++++++++++
deploy/README.md | 23 +++++++++++++++++++++--
deploy/deploy.sh | 9 +++++++++
3 files changed, 67 insertions(+), 2 deletions(-)
create mode 100644 deploy/Caddyfile.demo
diff --git a/deploy/Caddyfile.demo b/deploy/Caddyfile.demo
new file mode 100644
index 0000000..a425c68
--- /dev/null
+++ b/deploy/Caddyfile.demo
@@ -0,0 +1,37 @@
+# The live block on cloud-2, kept here so the config is reviewable in the repo.
+# Copy of /etc/caddy/Caddyfile's demo section — if you change one, change both.
+
+# Both names serve the same build from the same root. The prerendered HTML
+# carries pointing at the primeintellectgrowth name, so
+# the second hostname does not split search ranking between two copies.
+demo.primeintellectgrowth.com, demo.lumbridgecorp.com {
+ # REQUIRED, and its absence is silent. Without it Caddy builds a second
+ # server on *:443 that has never heard of this hostname, and public traffic
+ # — which NATs to 10.0.0.2 — falls through to an empty 200 behind a
+ # perfectly valid certificate. A --resolve check from cloud-2 still passes,
+ # so the only way to catch it is to curl the real hostname from elsewhere.
+ bind 10.0.0.2
+ import secweb
+ encode zstd gzip
+ root * /var/www/demo.primeintellectgrowth.com
+
+ # The whole point of this site is being found and read, so it says so
+ # explicitly. primeintellectgrowth.com itself serves noindex.
+ header X-Robots-Tag "index, follow"
+
+ @assets path /assets/*
+ header @assets Cache-Control "public, max-age=31536000, immutable"
+ @docs not path /assets/*
+ header @docs Cache-Control "no-cache"
+
+ # No SPA fallback. Every route is prerendered to its own index.html, so a
+ # fallback to the app shell would answer 200 for a typo'd URL and let a
+ # crawler index unlimited copies of the homepage.
+ try_files {path} {path}/index.html
+ file_server
+
+ handle_errors {
+ rewrite * /404.html
+ file_server
+ }
+}
diff --git a/deploy/README.md b/deploy/README.md
index a21d70b..cecdf1e 100644
--- a/deploy/README.md
+++ b/deploy/README.md
@@ -10,11 +10,30 @@ pnpm build && bash deploy/deploy.sh
| | |
|---|---|
+| Hostnames | `demo.primeintellectgrowth.com` (canonical) and `demo.lumbridgecorp.com` (alias) |
| Host | cloud-2, `ubuntu@100.92.185.76` (tailnet only) |
| Root | `/var/www/demo.primeintellectgrowth.com` |
| Snapshots | `…-rollbacks/`, last 10, hard-linked |
-| DNS | OCI zone `primeintellectgrowth.com` → `170.9.14.61`, explicit A record, no wildcard |
-| Caddy | a block appended to `/etc/caddy/Caddyfile` |
+| DNS | OCI zone `primeintellectgrowth.com` → `170.9.14.61`, explicit A record, no wildcard. The alias needs no record: `lumbridgecorp.com` has a wildcard |
+| Caddy | one block for both names, mirrored in `Caddyfile.demo` |
+
+## Two hostnames, one root
+
+Both names serve the same build. The prerendered HTML carries
+`` and `og:url` pointing at the **primeintellectgrowth**
+name on every route, so the alias does not split search ranking or make a shared
+link ambiguous about which site it belongs to.
+
+⚠️ **`lumbridgecorp.com` resolves on a wildcard.** Every subdomain of it points
+at cloud-2 whether or not Caddy has a block for it — so an unconfigured or
+mistyped name completes DNS, opens TLS, finds no certificate for that SNI, and
+fails the handshake with `ERR_SSL_PROTOCOL_ERROR`. That reads as "the site is
+broken" when it means "that is not a site". `primeintellectgrowth.com` has no
+wildcard, which is why the canonical name needed an explicit A record.
+
+`deploy.sh` smoke-tests the alias for exactly this reason: if the block is ever
+edited to drop the second name, the failure is a TLS error rather than a 404,
+and nothing else would notice.
## The trap that costs an afternoon
diff --git a/deploy/deploy.sh b/deploy/deploy.sh
index 80ffceb..410ba19 100755
--- a/deploy/deploy.sh
+++ b/deploy/deploy.sh
@@ -14,6 +14,11 @@ HOST="${PIG_DEMO_HOST:-ubuntu@100.92.185.76}"
ROOT="/var/www/demo.primeintellectgrowth.com"
SNAPS="${ROOT}-rollbacks"
URL="https://demo.primeintellectgrowth.com"
+# Served from the same root under a second name. Checked because DNS for
+# lumbridgecorp.com is a WILDCARD: the alias resolves whether or not Caddy knows
+# about it, and an unconfigured name fails the TLS handshake outright rather
+# than 404ing — which reads as "the site is down", not "wrong hostname".
+ALIAS="https://demo.lumbridgecorp.com"
cd "$(dirname "$0")/.."
@@ -69,4 +74,8 @@ for path in /sitemap.xml /robots.txt /og/wordle.png; do
[ "$code" = "200" ] || { echo "FAILED: $path returned $code"; exit 1; }
done
+alias_code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 "$ALIAS/" || echo 000)
+echo " alias $ALIAS -> $alias_code"
+[ "$alias_code" = "200" ] || { echo "FAILED: the alias hostname returned $alias_code"; exit 1; }
+
echo "==> live: $URL"