Files
PIG-Demo/deploy
karti-ai 1cd1d3bbba
ci / web (push) Successful in 3m34s
ci / python (push) Successful in 3m44s
Serve the site under demo.lumbridgecorp.com as well
One Caddy block, both names, same root. The prerendered HTML already carries
<link rel="canonical"> 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
2026-08-28 17:06:30 -07:00
..

Deploying

Static build, rsynced to cloud-2, served by Caddy.

pnpm build && bash deploy/deploy.sh

The pieces

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.com170.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 <link rel="canonical"> 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

bind 10.0.0.2 is mandatory in the Caddy block, and its absence is silent. Without it Caddy builds a second server on *:443 that has never heard of this hostname. Public traffic — which NATs to 10.0.0.2 — falls through to an empty 200 behind a perfectly valid certificate. Worse, a curl --resolve demo.primeintellectgrowth.com:443:127.0.0.1 from cloud-2 itself still passes.

deploy.sh therefore smoke-tests the real public hostname from the deploying machine and fails on a response under 1 kB.

Do not use PIG's deploy/Caddyfile.example as a template — it omits the bind.

Rolling back

ssh ubuntu@100.92.185.76
ls -1dt /var/www/demo.primeintellectgrowth.com-rollbacks/*/
sudo rsync -a --delete <that-dir>/ /var/www/demo.primeintellectgrowth.com/

No Caddy reload needed; the root path does not change.

Editing the live Caddyfile

Scope the edit to this site's block. Several sites on cloud-2 carry byte-identical header strings, so a naive global replace hits two of them. Slice between demo.primeintellectgrowth.com { and the next hostname, and assert the match is unique inside that slice.