Some checks failed
CI / fmt (pull_request) Successful in 1m22s
CI / clippy (pull_request) Successful in 3m46s
CI / test (1.85) (pull_request) Failing after 8m22s
CI / test (stable) (pull_request) Failing after 8m25s
CI / deny (pull_request) Failing after 1m24s
CI / sim-bench (stable) (pull_request) Failing after 11m2s
CI / image-build (4 images) (pull_request) Has been skipped
CI / smoke (all-in-one TLS sim call) (pull_request) Has been skipped
CI / smoke (T2 compose four-service) (pull_request) Has been skipped
CI / smoke (caddy reload during live call, zero drops) (pull_request) Has been skipped
CI / twilio-live (manual only) (pull_request) Has been skipped
Co-authored-by: Aaron D. Lee <himself@adlee.work> Co-committed-by: Aaron D. Lee <himself@adlee.work>
99 lines
4.2 KiB
Caddyfile
99 lines
4.2 KiB
Caddyfile
# deploy/Caddyfile — the edge config for rutster-edge (T2) + rutster-allinone (T1).
|
|
# Same file, same build (spec §3.2 + ADR-0011). Read by Caddy v2.8 (the
|
|
# custom xcaddy build from deploy/Dockerfile).
|
|
#
|
|
# Env vars (Caddyfile interpolation syntax {$VAR}):
|
|
# RUTSTER_DOMAIN — the public hostname (e.g. pbx.example.com). Required.
|
|
# RUTSTER_ACME_EMAIL — the Let's Encrypt account email. Required for ACME.
|
|
# RUTSTER_LOCAL_CERTS — set to "true" in CI to use Caddy's internal CA
|
|
# (no ACME round-trips, no rate-limit budget burns).
|
|
# Overrides the ACME block below via the `local_certs`
|
|
# global option.
|
|
#
|
|
# Timeouts (TLS brief §3(a); spec §2.1, §2.2, §3.1 invariant 3):
|
|
# * read_body 30s — Twilio webhooks fit comfortably in 30s (15s cap
|
|
# by invariant 6).
|
|
# * read_header 30s — same.
|
|
# * write 0 — disable; 20ms media frames must flush immediately.
|
|
# * idle 24h — the universal 60s-class default kills quiet WS;
|
|
# spec §2.1 invariant 3 sets max call duration 24h.
|
|
# * stream_close_delay 24h — above max call duration; the load-bearing
|
|
# mitigation for caddy #6420/#7222 (TLS brief §5
|
|
# risk 1; spec §9 reload-during-call smoke).
|
|
#
|
|
# X-Forwarded-* honesty (spec §3.1 invariant 5; plan-A Task 5
|
|
# reconstruct_public_url): Caddy sets these to the real client values via
|
|
# the `header_up` directives below. Engine-side RUTSTER_TRUSTED_PROXIES is
|
|
# the trust gate (fail-closed default).
|
|
{
|
|
# CI override: set RUTSTER_LOCAL_CERTS=true to use Caddy's internal CA
|
|
# (no ACME in CI; spec §9). Production leaves this unset.
|
|
{$RUTSTER_LOCAL_CERTS:local_certs_off} local_certs
|
|
|
|
# Send logs to stdout (s6-overlay / docker logs collects from there).
|
|
log {
|
|
output stdout
|
|
format console
|
|
}
|
|
}
|
|
|
|
# Default ACME email — overridden by RUTSTER_LOCAL_CERTS=true in CI.
|
|
{
|
|
email {$RUTSTER_ACME_EMAIL:you@example.com}
|
|
}
|
|
|
|
# Main site block — the public hostname.
|
|
{$RUTSTER_DOMAIN:localhost} {
|
|
encode zstd gzip
|
|
|
|
# The reverse_proxy to the FOB. 127.0.0.1:8080 is correct in T1
|
|
# (single container, loopback) AND T2 (compose: the engine service's
|
|
# `rutster-engine` DNS name resolves on the compose network; Caddy
|
|
# reaches it via that name — replace 127.0.0.1:8080 with
|
|
# http://engine:8080 in advance; here we use the loopback literal so
|
|
# the same Caddyfile works in both T1 and T2 spelled identically —
|
|
# for T2 deployments, the operator overrides the upstream via a env-
|
|
# substituted site-address block; the shipped default targets loopback
|
|
# for the bundled all-in-one single-container case which is the harder
|
|
# constraint).
|
|
#
|
|
# `header_up Host {host}` + X-Forwarded-* — sets the honest hop values
|
|
# (the engine's reconstruct_public_url reads these; spec §3.1 invariant 5).
|
|
# `header_up X-Forwarded-For {remote_host}` — included for completeness;
|
|
# the engine does NOT use X-Forwarded-For for signature validation, only
|
|
# X-Forwarded-Proto/Host. Forwarding the For header is standard proxy
|
|
# hygiene — engine-side RUTSTER_TRUSTED_PROXIES is the gate.
|
|
reverse_proxy 127.0.0.1:8080 {
|
|
header_up Host {host}
|
|
header_up X-Real-IP {remote_host}
|
|
header_up X-Forwarded-Proto {scheme}
|
|
header_up X-Forwarded-Host {host}
|
|
header_up X-Forwarded-For {remote_host}
|
|
|
|
# Tuned timeouts — the load-bearing ones for calls lasting hours.
|
|
transport http {
|
|
read_buffer 64KiB
|
|
write_buffer 64KiB
|
|
dial_timeout 5s
|
|
response_header_timeout 30s
|
|
}
|
|
|
|
# stream_close_delay above max call duration (24h) — the caddy
|
|
# #6420/#7222 mitigation (TLS brief §5 risk 1; spec §9 smoke).
|
|
# An operator Caddyfile reload mid-call would normally kill
|
|
# upgraded WS tunnels; the delay keeps them alive until the
|
|
# streams close naturally (the call ends) — verified by the
|
|
# reload-during-live-call CI smoke (Task 9).
|
|
stream_close_delay 24h
|
|
}
|
|
|
|
# Timeouts for the public-facing side.
|
|
servers {
|
|
read_body 30s
|
|
read_header 30s
|
|
write 0 # never write-timeout; 20ms frames self-flush
|
|
idle 24h # above max call duration — the universal 60s-class default kills quiet WS
|
|
}
|
|
}
|