1{ 2 email admin@filps.com 3 acme_ca https://acme-v02.api.letsencrypt.org/directory 4} 5 6aiops.filps.com { 7 # AI Software Factory — direct backend API surface. 8 # All API routes live here: /api/v1/* (incl. /api/v1/docs + /api/v1/health), 9 # /internal/*, /saml/*, /sso/*, /scim/v2/*. Used by webhook deliveries, 10 # API-key clients, IdP SCIM/ACS and programmatic access — NOT browser- 11 # facing (the browser uses notion.filps.com only, see below). 12 reverse_proxy 127.0.0.1:4000 { 13 header_up Host {host} 14 header_up X-Real-IP {remote_host} 15 # Stream SSE (e.g. /api/v1/ai/... streaming, automation logs). 16 flush_interval -1 17 } 18} 19 20play.filps.com { 21 @engine path /v1/* /actuator/* 22 reverse_proxy @engine localhost:8080 23 24 reverse_proxy localhost:8089 25} 26 27flydubai.filps.com { 28 reverse_proxy localhost:5173 29} 30 31play-api.filps.com { 32 reverse_proxy localhost:8080 33} 34 35intra.filps.com { 36 reverse_proxy 127.0.0.1:18083 { 37 header_up Host {host} 38 header_up X-Real-IP {remote_host} 39 } 40} 41 42notion.filps.com { 43 # ── AI Software Factory — THE app origin ──────────────────────────── 44 # Single-origin topology: the browser talks ONLY to this host (UI + API 45 # + WebSocket + S3 presigned URLs), so the host-scoped httpOnly 46 # `factory_refresh` cookie (no Domain= attr) satisfies the web 47 # middleware's session gate without cross-host cookie sharing. 48 # Every reverse_proxy preserves Host ({host}) so SigV4-signed S3 49 # requests keep a valid signed host through the proxy. 50 # `handle` blocks are mutually exclusive; they are ordered most- 51 # specific first. 52 53 # S3 (local shim :9000) — the two bucket prefixes, no path rewrite. 54 # S3_ENDPOINT=https://notion.filps.com (path-style); presigned GET/PUT 55 # URLs + the browser's direct upload XHR are same-origin. The matchers 56 # deliberately omit the trailing slash (`/factory-files*`) so the bare 57 # bucket root (ListObjects / bootstrap's anonymous-access check) also 58 # reaches the shim instead of falling through to the web app. 59 handle /factory-files* { 60 reverse_proxy 127.0.0.1:9000 { 61 header_up Host {host} 62 header_up X-Real-IP {remote_host} 63 } 64 } 65 66 handle /factory-thumbs* { 67 reverse_proxy 127.0.0.1:9000 { 68 header_up Host {host} 69 header_up X-Real-IP {remote_host} 70 } 71 } 72 73 # Realtime gateway (WebSocket upgrade at /realtime + SSE). 74 handle /realtime* { 75 reverse_proxy 127.0.0.1:4001 { 76 header_up Host {host} 77 header_up X-Real-IP {remote_host} 78 } 79 } 80 81 # SAML SSO: /saml/start/:orgSlug, /saml/metadata/:orgSlug, POST /saml/acs. 82 handle /saml/* { 83 reverse_proxy 127.0.0.1:4000 { 84 header_up Host {host} 85 header_up X-Real-IP {remote_host} 86 flush_interval -1 87 } 88 } 89 90 # OIDC SSO: /sso/oidc/:orgId/authorize|callback, /sso/start/:orgSlug. 91 handle /sso/* { 92 reverse_proxy 127.0.0.1:4000 { 93 header_up Host {host} 94 header_up X-Real-IP {remote_host} 95 flush_interval -1 96 } 97 } 98 99 # Backend API: everything under /api/v1 (incl. /api/v1/docs and 100 # /api/v1/health). (The web app's own /api/v1/health liveness route is 101 # shadowed publicly — container probes hit :3000 directly.) 102 handle /api/v1/* { 103 reverse_proxy 127.0.0.1:4000 { 104 header_up Host {host} 105 header_up X-Real-IP {remote_host} 106 # Stream SSE (AI streaming, long-running exports). 107 flush_interval -1 108 } 109 } 110 111 # Everything else → Next.js web app. 112 handle { 113 reverse_proxy 127.0.0.1:3000 { 114 header_up Host {host} 115 header_up X-Real-IP {remote_host} 116 } 117 } 118} 119 120countdown.filps.com { 121 root * /data/coding/flx-website 122 file_server 123} 124 125flxpop.com, www.flxpop.com { 126 root * /data/coding/flx-website 127 file_server 128} 129 130dockhand.filps.com { 131 log { 132 output file /var/log/caddy/dockhand.access.log 133 format json 134 } 135 136 @allowed remote_ip 13.206.168.181 137 138 handle @allowed { 139 reverse_proxy localhost:3000 { 140 header_up X-Real-IP {remote_host} 141 header_up Host {host} 142 } 143 } 144 145 respond "Forbidden" 403 146} 147