Add ${public_url} defaults.env placeholder for gateway-facing origin

Services often need their own public origin — the URL a browser loads them
at through the gateway — to populate CORS/WebSocket/secure-context allowlists.
Previously this had to be hardcoded in the app's own config, which silently
broke when the subdomain-routing migration changed the address (openclaw's
Control UI rejected its new origin).

${public_url} resolves at deploy to the service's gateway-facing base URL:
https://<name>.<gateway.domain> when exposed under tls: acme, else the
node-local http://localhost:<port>. It tracks gateway.domain, so a domain
change needs no per-app edit. Jobs (not exposed) don't get it.

Matches the TLS mode as the raw lowercased string == "acme", the same way the
Caddyfile generator does (the TLSMode enum is stale).
This commit is contained in:
2026-06-30 22:28:50 -07:00
parent d0075300e3
commit c28198dab6
2 changed files with 34 additions and 5 deletions

View File

@@ -469,6 +469,7 @@ Values may contain placeholders that castle resolves at deploy:
| `${port}` | the service's `expose.http.internal.port` (so it can't drift) |
| `${data_dir}` | `$CASTLE_DATA_DIR/<program-or-name>` (the dedicated data volume) |
| `${name}` | the deployment name |
| `${public_url}` | the service's gateway-facing base URL — `https://<name>.<domain>` when exposed under `tls: acme`, else the node-local `http://localhost:<port>`. The origin an app allowlists (CORS/WebSocket/secure-context); tracks `gateway.domain`, so a domain change needs no app edit. |
| `${secret:NAME}` | the contents of `~/.castle/secrets/NAME` |
Hardcode the values instead if you prefer; the placeholders just save you from