thermograph/infra/deploy/Caddyfile.vps1
Emi Griffith a83a0b7d32
All checks were successful
PR build (required check) / changes (pull_request) Successful in 6s
PR build (required check) / build-backend (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Has been skipped
secrets-guard / encrypted (pull_request) Successful in 9s
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 1s
forgejo: make dev.jinemi.com canonical (ROOT_URL and OAuth callback)
Forgejo derives every absolute URL from its single ROOT_URL, so this is what
moves clone URLs, the Google OAuth callback, webhook payload URLs and mail
links onto the new domain. Both redirect URIs are registered on the Google
OAuth client and were verified against Google before the flip — login is
SSO-only, so a mismatch locks everyone out of the UI including out of undoing
it. README documents the probe so the check is repeatable rather than assumed.

git.thermograph.org stays on the same Caddy site block and stays load-bearing:
the registry host baked into image names, the mesh /etc/hosts pins that make
the /v2/* matcher see a mesh source IP, and the runners' registered instance
URL all still use it. Renaming the registry is a separate migration; the docs
now say so where someone would otherwise retire the name as dead weight.

The stack has no auto-deploy, so this takes effect on a manual
`docker stack deploy` from the manager.
2026-08-01 09:32:12 -07:00

112 lines
4.1 KiB
Text

# /etc/caddy/Caddyfile on **vps1** (75.119.132.91) — the operational-programs box.
#
# vps1 serves:
# emigriffith.dev -> static portfolio site (from disk)
# dev.jinemi.com -> Forgejo, CANONICAL (Forgejo's ROOT_URL)
# git.thermograph.org -> Forgejo, same site block — still served and
# still needed: the registry host in image names,
# the mesh /etc/hosts pins and the runners' URLs
# all use it (see deploy/forgejo/caddy-git.conf)
# dashboard.thermograph.org -> Grafana (see observability/caddy-grafana.conf)
#
# and hosts the **dev** environment at dev.thermograph.org (below).
#
# beta.thermograph.org is NOT here either — beta moved to vps2, next to prod.
# That is the one edit in this file most likely to be made by mistake: a "beta"
# reference elsewhere in the repo that still points at 75.119.132.91 means this
# box, which no longer runs beta at all.
#
# Each domain's A/AAAA record must already point here — Caddy provisions a
# Let's Encrypt cert on first request and auto-renews.
emigriffith.dev {
encode zstd gzip
# Thermograph moved to its own domain. Send the old sub-path there with a
# permanent redirect, stripping the /thermograph prefix so deep links map
# straight across (…/thermograph/calendar -> thermograph.org/calendar). The
# bare /thermograph (no trailing slash) goes to the new root.
handle_path /thermograph/* {
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 that's its `dist/` output). file_server serves index.html for
# directories and returns a real 404 for missing paths.
handle {
root * /var/www/emigriffith
file_server
}
log {
output file /var/log/caddy/emigriffith.log
}
}
# 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 portfolio domain.
http://75.119.132.91 {
redir https://emigriffith.dev{uri} permanent
}
# Dev. Publicly resolvable, deliberately NOT publicly usable.
#
# Dev runs whatever branch is in flight — including unreviewed ones — on the
# same box as Forgejo and its CI runner. Three things make that acceptable, and
# all three are load-bearing:
#
# 1. The stack binds LOOPBACK (deploy/env-topology.sh sets DEV_BIND_ADDR to
# 127.0.0.1), so this site block is the only route in. Not even the mesh
# reaches the app directly.
# 2. basic auth, so a stumbled-upon URL is not a running build.
# 3. X-Robots-Tag: noindex, so dev never competes with thermograph.org in a
# search index the way a second copy of the same content otherwise would.
#
# Only :8137 is proxied. The dev overlay does not publish the frontend at all
# (docker-compose.dev.yml `ports: !reset null`) — the backend reverse-proxies to
# it internally, so one upstream serves the whole site here, unlike vps2 where
# Caddy path-splits across two ports.
#
# The credential below is a bcrypt hash, not a password. Rotate with:
# caddy hash-password --plaintext '<new>'
dev.thermograph.org {
encode zstd gzip
header {
X-Robots-Tag "noindex, nofollow"
}
# /healthz is deliberately OUTSIDE the auth boundary. It returns liveness and
# nothing else — no data, no version, no configuration — and Centralis polls
# it to report dev in `fleet_status`. Behind basic auth that poll gets a 401
# and dev reads as permanently down, which is how a monitoring blind spot
# gets created in the name of security.
@protected not path /healthz
basic_auth @protected {
dev $2a$14$LU5sNyxbop3HOsjhXB6ZrOQiveqhbcYVE6.Wi0bydAv4QhNpj4HMC
}
reverse_proxy 127.0.0.1:8137 {
health_uri /healthz
health_interval 15s
health_timeout 3s
health_status 2xx
}
log {
output file /var/log/caddy/dev.log {
roll_size 20MiB
roll_keep 5
}
}
}
# Optional: redirect www -> apex. Add the www CNAME/A record first, then
# uncomment.
# www.emigriffith.dev {
# redir https://emigriffith.dev{uri} permanent
# }