@@ -66,6 +66,10 @@ services:
6666 - " traefik.http.routers.http-webapp.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/`)"
6767 - " traefik.http.routers.http-webapp.service=http-webapp"
6868 - " traefik.http.routers.https-webapp.entryPoints=https"
69+ # Request-body cap (defined in compose.proxy.yaml). Router-scoped rather than entrypoint-wide
70+ # because the buffering middleware also buffers responses, which would stall the /api SSE
71+ # streams; the static SPA and the webhook receiver have no streaming responses.
72+ - " traefik.http.routers.https-webapp.middlewares=request-body-limit@docker"
6973 - " traefik.http.routers.https-webapp.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/`)"
7074 - " traefik.http.routers.https-webapp.service=https-webapp"
7175 - " traefik.http.routers.https-webapp.tls.certresolver=letsencrypt"
@@ -112,6 +116,8 @@ services:
112116 # Bounds heap sizing to this container; without it the JVM targets host RAM and co-located
113117 # services oversubscribe and swap. Hosts the NATS sync consumers, so it takes the largest limit.
114118 mem_limit : ${APPLICATION_SERVER_MEM_LIMIT:-5g}
119+ cpus : ${APPLICATION_SERVER_CPUS:-4.0}
120+ pids_limit : ${APPLICATION_SERVER_PIDS_LIMIT:-512}
115121 ports :
116122 - " 8080"
117123 environment :
@@ -136,6 +142,8 @@ services:
136142 DATABASE_USERNAME : root
137143 DATABASE_PASSWORD : root
138144 NATS_SERVER : nats://nats-server:4222
145+ NATS_USERNAME : ${NATS_USERNAME:?Set NATS_USERNAME}
146+ NATS_PASSWORD : ${NATS_PASSWORD:?Set NATS_PASSWORD}
139147 # Auth (Hephaestus-native; ADR 0017). State-cookie key MUST be base64 32-byte AES.
140148 HEPHAESTUS_AUTH_ISSUER : https://${APP_HOSTNAME}
141149 HEPHAESTUS_AUTH_STATE_COOKIE_KEY : ${HEPHAESTUS_AUTH_STATE_COOKIE_KEY}
@@ -256,7 +264,7 @@ services:
256264 THC_PATH : /actuator/health/liveness
257265 depends_on :
258266 postgres :
259- condition : service_started
267+ condition : service_healthy
260268 volume-init :
261269 condition : service_completed_successfully
262270 restart : unless-stopped
@@ -276,19 +284,25 @@ services:
276284 # the sandbox network IP and route requests to an unreachable internal network.
277285 - " traefik.docker.network=shared-network"
278286 - " traefik.http.middlewares.https-application-server-stripprefix.stripprefix.prefixes=/api"
287+ - " traefik.http.middlewares.edge-api-rate-limit.ratelimit.average=100"
288+ - " traefik.http.middlewares.edge-api-rate-limit.ratelimit.period=1s"
289+ - " traefik.http.middlewares.edge-api-rate-limit.ratelimit.burst=200"
279290 - " traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
280291 - " traefik.http.routers.http-application-server.entryPoints=http"
281292 - " traefik.http.routers.http-application-server.middlewares=redirect-to-https"
282293 - " traefik.http.routers.http-application-server.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/api`)"
283294 - " traefik.http.routers.http-application-server.service=http-application-server"
284295 - " traefik.http.routers.https-application-server.entryPoints=https"
285- - " traefik.http.routers.https-application-server.middlewares=https-application-server-stripprefix"
296+ - " traefik.http.routers.https-application-server.middlewares=edge-api-rate-limit, https-application-server-stripprefix"
286297 - " traefik.http.routers.https-application-server.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/api`)"
287298 - " traefik.http.routers.https-application-server.tls.certresolver=letsencrypt"
288299 - " traefik.http.routers.https-application-server.tls=true"
289300 - " traefik.http.routers.https-application-server.service=https-application-server"
290301 - " traefik.http.services.http-application-server.loadbalancer.server.port=8080"
291302 - " traefik.http.services.https-application-server.loadbalancer.server.port=8080"
303+ # The transport is defined by the proxy's file provider (compose.proxy.yaml): serversTransports
304+ # cannot be defined via docker labels, and referencing an undefined one disables this router.
305+ - " traefik.http.services.https-application-server.loadbalancer.serverstransport=application@file"
292306 - " traefik.http.routers.http-application-server.priority=5"
293307 - " traefik.http.routers.https-application-server.priority=10"
294308 # Replica affinity for workspace traffic (mentor lives here) — see docs/contributor/unified-pi-runtime.mdx.
@@ -325,6 +339,8 @@ services:
325339 image : " ${HEPHAESTUS_IMAGE_APPLICATION_SERVER:?verified release lock required}"
326340 # Bounds heap sizing to this container (see application-server).
327341 mem_limit : ${APPLICATION_WORKER_MEM_LIMIT:-3g}
342+ cpus : ${APPLICATION_WORKER_CPUS:-4.0}
343+ pids_limit : ${APPLICATION_WORKER_PIDS_LIMIT:-512}
328344 environment :
329345 # See application-server: the buildpack's 10M direct-memory default is too small.
330346 JAVA_TOOL_OPTIONS : " -XX:MaxDirectMemorySize=${APP_MAX_DIRECT_MEMORY:-128M}"
@@ -395,7 +411,9 @@ services:
395411 THC_PATH : /actuator/health/liveness
396412 depends_on :
397413 application-server :
398- condition : service_started
414+ condition : service_healthy
415+ postgres :
416+ condition : service_healthy
399417 volume-init :
400418 condition : service_completed_successfully
401419 restart : unless-stopped
0 commit comments