# cxai-stack — full CxWebApp + sidecar services compose. # Lives at /srv/cxai/compose/cxai-stack/compose.yaml on the VPS. # # All sidecars listen only on the internal `cxai` network. Only the cxwebapp # is bound to 127.0.0.1:8085 for Caddy to TLS-terminate in front of. name: cxai-stack networks: cxai: driver: bridge volumes: demand-reports: slack-state: diffusion-out: # Forge models + outputs + huggingface cache. Large (~5GB for SD 1.5 # base alone). Lives on /var/lib/docker/volumes on the VPS, which has # ~360GB free. forge-data: services: cxwebapp: image: registry.76-13-126-127.nip.io/cxai/cxwebapp:latest pull_policy: always container_name: cxai-cxwebapp restart: unless-stopped networks: [cxai] ports: ["127.0.0.1:8085:8080"] volumes: # Inject the freshly-built CxAI ADE build metadata over the baked-in # default so `/api/mac/info` reflects what's actually shipping. - ./cxai-mac-build-info.json:/opt/cxwebapp/share/cxai-mac/build-info.json:ro environment: CXWEBAPP_PORT: "8080" CXAI_DIFFUSION_UPSTREAM: "http://cxai-diffusion:8101" CXAI_DEMAND_UPSTREAM: "http://cxai-demand:8102" CXAI_LANG_UPSTREAM: "http://cxai-langsmith:8103" CXAI_SLACK_UPSTREAM: "http://cxai-slack:8104" CXAI_MAC_BUILD_INFO: "/opt/cxwebapp/share/cxai-mac/build-info.json" CXAI_MAC_DOWNLOAD_URL: "${CXAI_MAC_DOWNLOAD_URL:-}" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/api/health"] interval: 30s timeout: 3s retries: 3 # Real Stable-Diffusion-WebUI-Forge backend, CPU-only build (no GPU on # this VPS). Image is built from diffusion/forge/Dockerfile and serves # the standard /sdapi/v1 surface that cxai-diffusion's ForgeClient # talks to. First boot pulls SD 1.5 (~4GB) into forge-data. cxai-forge: image: registry.76-13-126-127.nip.io/cxai/cxai-forge:latest pull_policy: always container_name: cxai-forge restart: unless-stopped networks: [cxai] volumes: - forge-data:/data environment: # Reserve threads for the rest of the stack — EPYC has 8 cores. OMP_NUM_THREADS: "${CXAI_FORGE_THREADS:-6}" MKL_NUM_THREADS: "${CXAI_FORGE_THREADS:-6}" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:7860/sdapi/v1/options"] # Generous start period: first boot has to download SD 1.5. start_period: 600s interval: 30s timeout: 10s retries: 5 cxai-diffusion: image: registry.76-13-126-127.nip.io/cxai/cxai-diffusion-svc:latest pull_policy: always container_name: cxai-diffusion restart: unless-stopped networks: [cxai] depends_on: cxai-forge: condition: service_started volumes: - diffusion-out:/var/lib/cxai-diffusion/out environment: # Point at the in-network Forge container by default; override with # CXAI_DIFFUSION_BASE_URL to swap in a remote/hosted backend. (The # gateway reads CXAI_DIFFUSION_BASE_URL — see cxai_diffusion.config # ._resolve_base_url. Keep this var name aligned.) CXAI_DIFFUSION_BASE_URL: "${CXAI_DIFFUSION_BASE_URL:-http://cxai-forge:7860}" CXAI_DIFFUSION_GATEWAY_TOKEN: "${CXAI_DIFFUSION_GATEWAY_TOKEN:-}" CXAI_DIFFUSION_OUT_DIR: "/var/lib/cxai-diffusion/out" CXAI_DIFFUSION_QUANTUM_SEED: "${CXAI_DIFFUSION_QUANTUM_SEED:-1}" # qiskit/matplotlib both want a writable home; /app is owned by root # (image is built with USER cxai uid 10001 but no /home). MPLCONFIGDIR: "/tmp/matplotlib" HOME: "/tmp" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8101/healthz"] interval: 30s timeout: 5s retries: 3 cxai-demand: image: registry.76-13-126-127.nip.io/cxai/cxai-demand-svc:latest pull_policy: always container_name: cxai-demand restart: unless-stopped networks: [cxai] volumes: - demand-reports:/var/lib/cxai-demand/reports environment: OPENAI_API_KEY: "${OPENAI_API_KEY:-}" CXAI_BASE_URL: "${CXAI_BASE_URL:-https://cxai-studio.com/studio/v1}" CXAI_DRY_RUN: "${CXAI_DRY_RUN:-true}" CXAI_DEMAND_PORT: "8102" CXAI_DEMAND_REPORTS_DIR: "/var/lib/cxai-demand/reports" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8102/healthz"] interval: 30s timeout: 5s retries: 3 cxai-langsmith: image: registry.76-13-126-127.nip.io/cxai/cxai-langsmith-svc:latest pull_policy: always container_name: cxai-langsmith restart: unless-stopped networks: [cxai] environment: CXBASE_TRANSPORT: "${CXBASE_TRANSPORT:-bearer}" CXBASE_BASE_URL: "${CXBASE_BASE_URL:-https://cxai-studio.com/studio/v1}" CXBASE_BEARER_TOKEN: "${CXBASE_BEARER_TOKEN:-freecc}" CXAI_MCP_URL: "${CXAI_MCP_URL:-http://cxai-mac.tail91d296.ts.net/mcp}" LANGSMITH_API_KEY: "${LANGSMITH_API_KEY:-}" LANGSMITH_TRACING: "${LANGSMITH_TRACING:-false}" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8103/healthz"] interval: 30s timeout: 5s retries: 3 cxai-slack: image: registry.76-13-126-127.nip.io/cxai/cxai-slack-svc:latest pull_policy: always container_name: cxai-slack restart: unless-stopped networks: [cxai] volumes: - slack-state:/var/lib/cxai-slack environment: SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN:-}" SLACK_APP_TOKEN: "${SLACK_APP_TOKEN:-}" SLACK_APP_SIGNING_SECRET: "${SLACK_APP_SIGNING_SECRET:-}" SLACK_APP_ID: "${SLACK_APP_ID:-}" SLACK_APP_CLIENT_ID: "${SLACK_APP_CLIENT_ID:-}" SLACK_BOT_WEBHOOK_URL: "${SLACK_BOT_WEBHOOK_URL:-}" USER_OAUTH_TOKEN: "${USER_OAUTH_TOKEN:-}" OPENAI_API_KEY: "${OPENAI_API_KEY:-}" OPENAI_BASE_URL: "${OPENAI_BASE_URL:-}" OPENAI_MODEL: "${OPENAI_MODEL:-}" CXAI_GATEWAY_TOKEN: "${CXAI_GATEWAY_TOKEN:-${CXBASE_BEARER_TOKEN:-freecc}}" CXAI_GATEWAY_URL: "${CXAI_GATEWAY_URL:-${CXBASE_BASE_URL:-https://cxai-studio.com/studio/v1}}" CXAI_GATEWAY_MODEL: "${CXAI_GATEWAY_MODEL:-${CXBASE_MCP_MODEL:-claude-sonnet-4}}" XDG_STATE_HOME: "/var/lib/cxai-slack" HOME: "/home/cxai" CXAI_SANDBOX_ROOT: "/tmp/cxai-sandbox" CXAI_SLACK_SVC_PORT: "8104" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8104/healthz"] interval: 30s timeout: 5s retries: 3