# ============================================================================= # SimpleAudit Studio — single-origin chat routing (subpath Open WebUI) # # The routing shape enabled by the subpath fork built via # deploy/openwebui-subpath/build.sh (published as # ghcr.io/sushantgautam/open-webui:v0.12.4.5-subpath). It replaces the old # cross-origin iframe model (Caddyfile.chat on :8801) with one origin / one # port: # # https://studio.example.com # ├── /chat/... -> Open WebUI (subpath build, served AT /chat) # ├── /playground/... -> Studio's wrapper page (model-picker bar + iframe of /chat/) # └── everything -> Studio (Django) # # Only THIS container publishes a port. Studio (web) and Open WebUI publish # none — everything the browser sees goes through here. # # THE CRITICAL DETAIL (verified empirically): use `handle`, NOT `handle_path`. # handle_path /chat/* => strips the prefix and forwards /foo, but the # subpath fork serves its socket at the FULL path # /chat/ws/socket.io (engineio matches the raw path, # not root_path-relative) -> the socket 404s. # handle /chat/* => forwards /chat/foo as-is, which is exactly what # a WEBUI_SUBPATH=/chat build expects. # # ============================================================================= { auto_https off admin off } :{$STUDIO_PORT:8000} { # Never let a client supply its own identity. request_header -X-Studio-Email request_header -X-Studio-Name request_header -X-Studio-Role # Studio's /playground/ iframe points at the bare subpath with query params # (/chat?models=...). `handle /chat/*` does NOT match a bare /chat, so # send it to /chat/ (query preserved) before route selection. rewrite /chat /chat/ # Studio's chat embed stylesheet: the subpath build requests # /chat/static/custom.css on every page. Caddy intercepts it (before the # /chat/* proxy) and proxies it to Studio's /chat/css-mask, which serves # chat/embed.css normally and chat/embed_admin.css for an admin's iframe # session (stamped by /chat/authz when the page loads with ?embed=admin). # The session cookie rides the request, so no Caddy-side state is needed. handle /chat/static/custom.css { reverse_proxy {$STUDIO_UPSTREAM:web:8000} { rewrite /chat/css-mask } } # Studio's chat embed mask script: the subpath build's static/loader.js # is a 0-byte no-op (the SPA's first