# the dev/e2e stack's routing. Sibling of docker/prod/Caddyfile (the # production image's front door): same routes, same blocks — only the # upstreams differ. Change the two files together. { admin off # disable the admin API # every served request is an INFO access log line, and nothing here # reads them; warnings and errors still come through. log { level WARN } } (common) { request_body { max_size 30MB # must be higher than file upload limit } header -Server } :8080 { import common # /api/x/* is core's internal, auth-less service-to-service surface — # it must never be reachable through the front door. /api/apps/* is the # opposite: GitHub and Slack deliver their webhooks and OAuth callbacks # there, so it stays open and is guarded by request signatures instead. handle /core/api/x/* { respond 403 } # /api/internal/* is auth-realtime's unauthenticated service-to-service # surface (core calls it directly over the container network) — it must # never be reachable through the front door either. handle /auth-realtime/api/internal/* { respond 403 } # OAuth discovery for the MCP surface. Spec-compliant MCP clients # resolve these documents at the front-door origin root (RFC 9728 / # RFC 8414 well-known paths), so they are rewritten onto better-auth's # basePath'd endpoints regardless of any issuer path suffix the client # appends. # served by the mcp plugin's request hook, which matches the original # root-anchored path — no rewrite. handle /.well-known/oauth-protected-resource* { reverse_proxy auth-realtime:8081 } handle /.well-known/oauth-authorization-server* { rewrite * /api/auth/.well-known/oauth-authorization-server reverse_proxy auth-realtime:8081 } handle /.well-known/openid-configuration* { rewrite * /api/auth/.well-known/openid-configuration reverse_proxy auth-realtime:8081 } # better-auth builds its OAuth endpoint URLs from the bare origin plus # its /api/auth basePath, so the authorization-server metadata points # MCP clients at /api/auth/... on the front door. Proxy that prefix to # auth-realtime as-is (no path strip — the service serves /api/auth # natively). handle /api/auth/* { reverse_proxy auth-realtime:8081 } handle_path /core/* { reverse_proxy core:8080 } handle_path /auth-realtime/* { reverse_proxy auth-realtime:8081 } handle { reverse_proxy web:3000 } } :8082 { import common reverse_proxy changedetection:5000 } :8084 { import common reverse_proxy mailpit:8025 }