1cd1d3bbba
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
38 lines
1.5 KiB
Caddyfile
38 lines
1.5 KiB
Caddyfile
# 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 <link rel=canonical> 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
|
|
}
|
|
}
|