name: wyndham-arr services: web: build: context: . image: "${ARR_IMAGE_NAME:-wyndham-arr}:${ARR_IMAGE_TAG:-latest}" restart: unless-stopped init: true command: - python - -m - arr_web.run - --host - 0.0.0.0 - --port - "8765" - --enable-processing - --secure-cookies environment: ARR_DATABASE_URL: "${ARR_DATABASE_URL:?set ARR_DATABASE_URL in deploy/.env.production}" ARR_OBJECT_PREFIX: "${ARR_OBJECT_PREFIX:-arr}" ARR_OSS_REGION: "${ARR_OSS_REGION:?set ARR_OSS_REGION}" ARR_OSS_ENDPOINT: "${ARR_OSS_ENDPOINT:-}" ARR_OSS_BUCKET: "${ARR_OSS_BUCKET:?set ARR_OSS_BUCKET}" OSS_ACCESS_KEY_ID: "${OSS_ACCESS_KEY_ID:?set OSS_ACCESS_KEY_ID or adapt Compose for a RAM role}" OSS_ACCESS_KEY_SECRET: "${OSS_ACCESS_KEY_SECRET:?set OSS_ACCESS_KEY_SECRET or adapt Compose for a RAM role}" OSS_SESSION_TOKEN: "${OSS_SESSION_TOKEN:-}" DEERFLOW_BASE_URL: "${DEERFLOW_BASE_URL:?set DEERFLOW_BASE_URL}" DEERFLOW_OPEN_API_KEY: "${DEERFLOW_OPEN_API_KEY:?set DEERFLOW_OPEN_API_KEY}" DEERFLOW_AUTH_MODE: "${DEERFLOW_AUTH_MODE:-bearer}" DEERFLOW_TIMEOUT_SECONDS: "${DEERFLOW_TIMEOUT_SECONDS:-60}" DEERFLOW_CONNECT_TIMEOUT_SECONDS: "${DEERFLOW_CONNECT_TIMEOUT_SECONDS:-10}" DEERFLOW_SESSION_DB: /app/runtime/agent_sessions.sqlite3 ARR_AGENT_RESULT_HMAC_KEY_ID: "${ARR_AGENT_RESULT_HMAC_KEY_ID:?set ARR_AGENT_RESULT_HMAC_KEY_ID}" ARR_AGENT_RESULT_HMAC_KEY_B64: "${ARR_AGENT_RESULT_HMAC_KEY_B64:?set ARR_AGENT_RESULT_HMAC_KEY_B64}" ARR_AGENT_RESULT_MAX_AGE_SECONDS: "${ARR_AGENT_RESULT_MAX_AGE_SECONDS:-600}" expose: - "8765" volumes: - arr_runtime:/app/runtime - arr_outputs:/app/outputs tmpfs: - /tmp:size=64m,mode=1777 security_opt: - no-new-privileges:true cap_drop: - ALL healthcheck: test: - CMD - python - -c - >- import json,sys,urllib.request; data=json.load(urllib.request.urlopen('http://127.0.0.1:8765/api/health',timeout=5))['data']; sys.exit(0 if data.get('database_ready') and data.get('processing_ready') else 1) interval: 15s timeout: 6s retries: 12 start_period: 20s mcp: image: "${ARR_IMAGE_NAME:-wyndham-arr}:${ARR_IMAGE_TAG:-latest}" restart: unless-stopped init: true command: - python - -m - arr_mcp.run - --host - 0.0.0.0 - --port - "8890" - --max-concurrency - "${ARR_MCP_MAX_CONCURRENCY:-2}" - --allowed-host - "${MCP_PUBLIC_HOST:?set MCP_PUBLIC_HOST}" - --allowed-host - "${MCP_PUBLIC_HOST}:*" environment: ARR_DATABASE_URL: "${ARR_DATABASE_URL:?set ARR_DATABASE_URL in deploy/.env.production}" ARR_OBJECT_PREFIX: "${ARR_OBJECT_PREFIX:-arr}" ARR_OSS_REGION: "${ARR_OSS_REGION:?set ARR_OSS_REGION}" ARR_OSS_ENDPOINT: "${ARR_OSS_ENDPOINT:-}" ARR_OSS_BUCKET: "${ARR_OSS_BUCKET:?set ARR_OSS_BUCKET}" OSS_ACCESS_KEY_ID: "${OSS_ACCESS_KEY_ID:?set OSS_ACCESS_KEY_ID or adapt Compose for a RAM role}" OSS_ACCESS_KEY_SECRET: "${OSS_ACCESS_KEY_SECRET:?set OSS_ACCESS_KEY_SECRET or adapt Compose for a RAM role}" OSS_SESSION_TOKEN: "${OSS_SESSION_TOKEN:-}" ARR_MCP_BEARER_TOKEN: "${ARR_MCP_BEARER_TOKEN:?set ARR_MCP_BEARER_TOKEN}" expose: - "8890" tmpfs: - /tmp:size=64m,mode=1777 security_opt: - no-new-privileges:true cap_drop: - ALL healthcheck: test: - CMD - python - -c - >- import socket; connection=socket.create_connection(('127.0.0.1',8890),5); connection.close() interval: 15s timeout: 6s retries: 12 start_period: 20s caddy: image: caddy:2.10-alpine restart: unless-stopped depends_on: web: condition: service_healthy mcp: condition: service_healthy environment: WEB_PUBLIC_HOST: "${WEB_PUBLIC_HOST:?set WEB_PUBLIC_HOST}" MCP_PUBLIC_HOST: "${MCP_PUBLIC_HOST:?set MCP_PUBLIC_HOST}" ACME_EMAIL: "${ACME_EMAIL:?set ACME_EMAIL}" WEB_BASIC_AUTH_USER: "${WEB_BASIC_AUTH_USER:?set WEB_BASIC_AUTH_USER}" WEB_BASIC_AUTH_PASSWORD_HASH: "${WEB_BASIC_AUTH_PASSWORD_HASH:?set WEB_BASIC_AUTH_PASSWORD_HASH}" ports: - "80:80" - "443:443" - "443:443/udp" volumes: - ./deploy/Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config security_opt: - no-new-privileges:true volumes: arr_runtime: arr_outputs: caddy_data: caddy_config: