6.5 KiB
Edge Routing Fallback: Per-Project Subdomains
Status: Contingency plan. Only implement if subpath routing (#704 / #708) proves unworkable.
Context
The primary approach routes services under subpaths of <project>.disinto.ai:
| Service | Primary (subpath) |
|---|---|
| Forgejo | <project>.disinto.ai/forge/ |
| Woodpecker | <project>.disinto.ai/ci/ |
| Chat | <project>.disinto.ai/chat/ |
| Staging | <project>.disinto.ai/staging/ |
The fallback uses per-service subdomains instead:
| Service | Fallback (subdomain) |
|---|---|
| Forgejo | forge.<project>.disinto.ai/ |
| Woodpecker | ci.<project>.disinto.ai/ |
| Chat | chat.<project>.disinto.ai/ |
| Staging | <project>.disinto.ai/ (root) |
The wildcard cert from #621 already covers *.<project>.disinto.ai — no new
DNS records or certs are needed for sub-subdomains because *.disinto.ai
matches one level deep. For sub-subdomains like forge.<project>.disinto.ai
we would need to add a second wildcard (*.*.disinto.ai) or explicit DNS
records per project. Both are straightforward with the existing Gandi DNS-01
setup.
Pivot Decision Criteria
Pivot if:
- Forgejo
ROOT_URLunder a subpath (/forge/) causes redirect loops that cannot be fixed withX-Forwarded-Prefixor Caddyuri strip_prefix. - Woodpecker's
WOODPECKER_HOSTdoes not honour subpath prefixes, causing OAuth callback mismatches that persist after adjusting redirect URIs. - Forward-auth on
/chat/*conflicts with Forgejo's own OAuth flow when both share the same origin (cookie collision, CSRF token mismatch).
Do NOT pivot if:
- Forgejo login redirects to
/instead of/forge/— fixable with Caddyhandle_path+uri prefixrewrite. - Woodpecker UI assets 404 under
/ci/— fixable with asset prefix config (WOODPECKER_ROOT_PATH). - A single OAuth app needs a second redirect URI — Forgejo supports multiple
redirect_urisin the same app.
Fallback Topology
Caddyfile
Replace the single :80 block with four host blocks:
# Main project domain — staging / landing
<project>.disinto.ai {
reverse_proxy staging:80
}
# Forgejo — root path, no subpath rewrite needed
forge.<project>.disinto.ai {
reverse_proxy forgejo:3000
}
# Woodpecker CI — root path
ci.<project>.disinto.ai {
reverse_proxy woodpecker:8000
}
# Chat — with forward_auth (same as #709, but on its own host)
chat.<project>.disinto.ai {
handle /login {
reverse_proxy chat:8080
}
handle /oauth/callback {
reverse_proxy chat:8080
}
handle /* {
forward_auth chat:8080 {
uri /auth/verify
copy_headers X-Forwarded-User
header_up X-Forward-Auth-Secret {$FORWARD_AUTH_SECRET}
}
reverse_proxy chat:8080
}
}
Current file: docker/Caddyfile (generated by lib/generators.sh:_generate_caddyfile_impl, line ~596).
Service Configuration Changes
| Variable / Setting | Current (subpath) | Fallback (subdomain) | File |
|---|---|---|---|
Forgejo ROOT_URL |
https://<project>.disinto.ai/forge/ |
https://forge.<project>.disinto.ai/ |
forgejo app.ini |
WOODPECKER_HOST |
http://localhost:8000 (subpath via proxy) |
https://ci.<project>.disinto.ai |
lib/ci-setup.sh line ~164 |
| Woodpecker OAuth redirect | https://<project>.disinto.ai/ci/authorize |
https://ci.<project>.disinto.ai/authorize |
lib/ci-setup.sh line ~153 |
| Chat OAuth redirect | https://<project>.disinto.ai/chat/oauth/callback |
https://chat.<project>.disinto.ai/oauth/callback |
lib/ci-setup.sh line ~188 |
EDGE_TUNNEL_FQDN |
<project>.disinto.ai |
unchanged (main domain) | lib/generators.sh line ~432 |
New Environment Variables (pivot only)
These would be added to lib/generators.sh _generate_compose_impl() in the
edge service environment block (currently line ~415):
| Variable | Value |
|---|---|
EDGE_TUNNEL_FQDN_FORGE |
forge.<project>.disinto.ai |
EDGE_TUNNEL_FQDN_CI |
ci.<project>.disinto.ai |
EDGE_TUNNEL_FQDN_CHAT |
chat.<project>.disinto.ai |
DNS
No new records needed if the registrar supports *.*.disinto.ai wildcards.
Otherwise, add explicit A/CNAME records per project:
forge.<project>.disinto.ai → edge server IP
ci.<project>.disinto.ai → edge server IP
chat.<project>.disinto.ai → edge server IP
The edge server already handles TLS via Caddy's automatic HTTPS with the existing ACME / DNS-01 challenge.
Edge Control (tools/edge-control/register.sh)
Currently do_register() creates a single route for <project>.disinto.ai.
The fallback would need to register four routes (or accept a --subdomain
parameter). See the TODO in register.sh.
Files to Change on Pivot
| File | What changes |
|---|---|
docker/Caddyfile |
Replace single host block → four host blocks (see above) |
lib/generators.sh |
Add EDGE_TUNNEL_FQDN_{FORGE,CI,CHAT} env vars to compose |
lib/ci-setup.sh ~line 153 |
Woodpecker OAuth redirect URI → ci.<project> subdomain |
lib/ci-setup.sh ~line 188 |
Chat OAuth redirect URI → chat.<project> subdomain |
tools/edge-control/register.sh |
Register four routes per project instead of one |
tools/edge-control/lib/caddy.sh |
add_route() gains subdomain support |
forgejo app.ini |
ROOT_URL → https://forge.<project>.disinto.ai/ |
Estimated effort for a full pivot: under one day given this plan.