Serve the app on thermograph.org at root; redirect emigriffith.dev/thermograph (#91)

Move Thermograph to its own domain. thermograph.org now serves the app at its
root, and emigriffith.dev/thermograph* permanently redirects there (prefix
stripped, so deep links map straight across).

- app.py: BASE now supports an empty root prefix. THERMOGRAPH_BASE=/ (or empty)
  yields BASE="" so routes sit at "/", "/calendar", "/api/v2/…" with no double
  slashes; the bare-base redirect is skipped and the static mount falls back to
  "/". Non-empty values keep the existing "/thermograph" sub-path behavior
  unchanged (backward compatible).
- deploy/Caddyfile: add a thermograph.org site block reverse-proxying to the
  uvicorn on 127.0.0.1:8137; turn emigriffith.dev's /thermograph handler into a
  permanent redirect to thermograph.org (handle_path strips the prefix; the bare
  /thermograph goes to the root).
- deploy/thermograph.env.example: default THERMOGRAPH_BASE=/ (app owns the domain).
- DEPLOY.md: document the two-domain layout and that deploy.sh does not ship the
  Caddyfile or env — those are applied on the VPS by hand.

The frontend already uses base-relative URLs, so it follows the root base with no
changes. Verified both modes locally (root serves /, /calendar, /api/v2/*; the
/thermograph sub-path still redirects bare→slash and 404s at root) and the full
test suite (123) passes.
This commit is contained in:
Emi Griffith 2026-07-15 12:58:32 -07:00 committed by GitHub
parent 9d315f81c6
commit 00d4c054c4
2 changed files with 39 additions and 18 deletions

View file

@ -1,25 +1,41 @@
# /etc/caddy/Caddyfile on the VPS. # /etc/caddy/Caddyfile on the VPS.
# The domain's A/AAAA record must already point at this VPS — Caddy provisions a # Each domain's A/AAAA record must already point at this VPS — Caddy provisions a
# Let's Encrypt cert on first request and auto-renews. Nothing else to do for TLS # Let's Encrypt cert on first request and auto-renews. Nothing else to do for TLS
# (just make sure ports 80 and 443 are open). # (just make sure ports 80 and 443 are open).
# #
# Layout on this domain: # Layout:
# / -> static portfolio site (served straight from disk) # thermograph.org/* -> the Thermograph app (reverse-proxied to uvicorn)
# /thermograph/* -> reverse-proxied to the Thermograph uvicorn (loopback) # emigriffith.dev/ -> static portfolio site (served straight from disk)
# emigriffith.dev/thermograph* -> permanent redirect to thermograph.org (the app moved)
# #
# Thermograph must run with THERMOGRAPH_BASE=/thermograph (see /etc/thermograph.env) # Thermograph now owns thermograph.org's root, so it must run with
# so the app serves itself under that prefix. The app no longer claims "/", so the # THERMOGRAPH_BASE=/ (see /etc/thermograph.env) — the app serves its pages, assets
# root is free for the portfolio. # and API at "/" with no sub-path prefix. One uvicorn on 127.0.0.1:8137 backs both
# thermograph.org (proxied) and the emigriffith.dev redirect.
thermograph.org {
encode zstd gzip
# The app serves everything at the root now (THERMOGRAPH_BASE=/).
reverse_proxy 127.0.0.1:8137
log {
output file /var/log/caddy/thermograph.log
}
}
emigriffith.dev { emigriffith.dev {
encode zstd gzip encode zstd gzip
# Thermograph — the app serves all pages, assets, and API under /thermograph. # Thermograph moved to its own domain. Send the old sub-path there with a
# Match both the bare prefix and everything beneath it; the app redirects the # permanent redirect, stripping the /thermograph prefix so deep links map
# bare /thermograph to /thermograph/. # straight across (…/thermograph/calendar -> thermograph.org/calendar). The
@thermograph path /thermograph /thermograph/* # bare /thermograph (no trailing slash) goes to the new root.
handle @thermograph { handle_path /thermograph/* {
reverse_proxy 127.0.0.1:8137 redir https://thermograph.org{uri} permanent
}
handle /thermograph {
redir https://thermograph.org/ permanent
} }
# Portfolio at the root. Point `root` at the built static site (for the Astro # Portfolio at the root. Point `root` at the built static site (for the Astro
@ -36,12 +52,16 @@ emigriffith.dev {
} }
# Old bookmarks to the raw IP (the pre-domain URL) would otherwise get bounced to # Old bookmarks to the raw IP (the pre-domain URL) would otherwise get bounced to
# HTTPS-on-the-IP, which has no cert and fails. Redirect them to the real domain. # HTTPS-on-the-IP, which has no cert and fails. Redirect them to the portfolio domain.
http://75.119.132.91 { http://75.119.132.91 {
redir https://emigriffith.dev{uri} permanent redir https://emigriffith.dev{uri} permanent
} }
# Optional: redirect www -> apex. Add a www CNAME/A record first, then uncomment. # Optional: redirect www -> apex for either domain. Add the www CNAME/A record
# first, then uncomment the matching block.
# www.emigriffith.dev { # www.emigriffith.dev {
# redir https://emigriffith.dev{uri} permanent # redir https://emigriffith.dev{uri} permanent
# } # }
# www.thermograph.org {
# redir https://thermograph.org{uri} permanent
# }

View file

@ -5,7 +5,8 @@
PORT=8137 PORT=8137
# Base path the app is served under. # Base path the app is served under.
# / -> app at the domain root (Thermograph owns the whole domain —
# this is what the Caddyfile expects: thermograph.org proxies "/")
# /thermograph -> app under a sub-path (share the host with other apps, e.g. a # /thermograph -> app under a sub-path (share the host with other apps, e.g. a
# portfolio at the root — this is what the Caddyfile expects) # portfolio at the root)
# / -> app at the domain root (only if Thermograph owns the whole domain) THERMOGRAPH_BASE=/
THERMOGRAPH_BASE=/thermograph