CxWebApp/compose/cxai-stack.yaml
CxAI Agent 055e350108
Some checks are pending
build-and-push / image (push) Waiting to run
feat: initial CxWebApp (macOS shell + swift-app wired to CxLLM-SDK)
2026-05-16 14:32:01 -05:00

172 lines
6.5 KiB
YAML

# 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