From c38375c0f4dd85e4fa11739f4f4bf349d78a35a3 Mon Sep 17 00:00:00 2001 From: ArthurErlich Date: Thu, 3 Sep 2026 20:37:49 +0200 Subject: [PATCH] fix(omniroute): add required WS bridge secret, memory ceiling, shutdown grace period Cross-checked the deployment against OmniRoute's own docs (docs/reference/ENVIRONMENT.md, docs/guides/DOCKER_GUIDE.md) and found three gaps from the original migration: - OMNIROUTE_WS_BRIDGE_SECRET was entirely missing - ENVIRONMENT.md marks it REQUIRED (production), for the internal Codex Responses WebSocket bridge. docker compose config validated fine without it (compose doesn't know omniroute's own required-var list), so this went unnoticed until checking the docs directly. - No mem_limit/OMNIROUTE_MEMORY_MB - the Docker guide is explicit that the 1024MB default heap is dashboard-only sized; coding-agent workloads (every client this stack has) need OMNIROUTE_MEMORY_MB=8192 and a 10+ GiB container ceiling. Set both. - No stop_grace_period - the guide's --stop-timeout 40 equivalent, so SQLite WAL changes checkpoint back into the main DB file on shutdown instead of getting killed mid-write. Redis checked and confirmed correctly absent - OmniRoute uses SQLite only, no Redis anywhere in its docs. Still open: whether API_PORT actually isolates /dashboard and /api/* from the published port, or bridges everything through (see issue #31) - OmniRoute's own ARCHITECTURE.md doesn't document split-port mode as a real security boundary, and the live "[API Bridge] ... -> dashboard" log line is ambiguous. Waiting on a live curl test against proxy-ai.home before treating that as resolved. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01VPZ6TogJiYxG8E4EQBB197 --- .env.example | 3 +++ docker-compose.yml | 15 +++++++++++++++ scripts/update.sh | 1 + 3 files changed, 19 insertions(+) diff --git a/.env.example b/.env.example index 4899635..372638f 100644 --- a/.env.example +++ b/.env.example @@ -63,6 +63,9 @@ OMNIROUTE_STORAGE_ENCRYPTION_KEY= # Per-deployment salts — random is fine, just needs to be stable: OMNIROUTE_MACHINE_ID_SALT= OMNIROUTE_CLI_SALT= +# Required (production) — shared secret for the internal Codex Responses +# WebSocket bridge. Random value, filled in automatically: +OMNIROUTE_WS_BRIDGE_SECRET= # Per-workload virtual keys (one per client that calls the gateway) have no # scripted /key/generate equivalent yet — omniroute's key-creation endpoint # needs a dashboard login session, not a static bearer key (see issue #37). diff --git a/docker-compose.yml b/docker-compose.yml index b353b74..ef735a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,6 +84,15 @@ services: # default (SSRF guard against public-provider spoofing). - OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS=true - OMNIROUTE_ALLOW_LOCAL_PROVIDER_URLS=true + # Required (production) per docs/reference/ENVIRONMENT.md — shared + # secret for the internal Codex Responses WebSocket bridge. Missed on + # first pass; docker-compose config validated fine without it, but + # the docs are explicit this one's required, not optional. + - OMNIROUTE_WS_BRIDGE_SECRET=${OMNIROUTE_WS_BRIDGE_SECRET} + # Default heap (1024MB) is dashboard-only sized per OmniRoute's own + # Docker guide — every client here is a coding CLI, which needs the + # larger figure the guide recommends. Paired with mem_limit below. + - OMNIROUTE_MEMORY_MB=8192 # Same reasoning as litellm's extra_hosts entry below — ai-stack's bridge # network can't resolve search.home on its own. extra_hosts: @@ -95,6 +104,12 @@ services: # to also change omniroute's own internal port config to match. ports: - "${OMNIROUTE_PORT:-4000}:${OMNIROUTE_API_PORT:-20129}" + # 10+ GiB ceiling per OmniRoute's Docker guide, matching + # OMNIROUTE_MEMORY_MB=8192 above. + mem_limit: 10g + # SQLite WAL needs time to checkpoint back into the main DB file on + # shutdown — the Docker guide's --stop-timeout 40 equivalent. + stop_grace_period: 40s restart: unless-stopped networks: [ai-stack] # ponytail: TCP-connect check, not an HTTP /healthz GET — the image has diff --git a/scripts/update.sh b/scripts/update.sh index a3b03a3..37d76f4 100755 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -43,6 +43,7 @@ set_if_blank OMNIROUTE_API_KEY_SECRET "$(openssl rand -hex 32)" set_if_blank OMNIROUTE_STORAGE_ENCRYPTION_KEY "$(openssl rand -hex 32)" set_if_blank OMNIROUTE_MACHINE_ID_SALT "$(openssl rand -hex 16)" set_if_blank OMNIROUTE_CLI_SALT "$(openssl rand -hex 16)" +set_if_blank OMNIROUTE_WS_BRIDGE_SECRET "$(openssl rand -hex 32)" echo "==> resolving SEARXNG_LAN_IP" # search.home is a LAN mDNS/local-DNS name — resolvable from this host, just