name: roomote x-roomote-production-env: &roomote-production-env NODE_ENV: production R_APP_ENV: production DATABASE_URL: ${DATABASE_URL:?DATABASE_URL is required} REDIS_URL: ${REDIS_URL:?REDIS_URL is required} S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000} S3_PRESIGN_ENDPOINT: ${S3_PRESIGN_ENDPOINT:-https://${ROOMOTE_APP_DOMAIN:?ROOMOTE_APP_DOMAIN is required}} S3_REGION: ${S3_REGION:-us-east-1} S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?S3_ACCESS_KEY_ID is required} S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?S3_SECRET_ACCESS_KEY is required} S3_BUCKET_ARTIFACTS: ${S3_BUCKET_ARTIFACTS:-roomote-artifacts} JOB_AUTH_PRIVATE_KEY: ${JOB_AUTH_PRIVATE_KEY:?JOB_AUTH_PRIVATE_KEY is required} JOB_AUTH_PUBLIC_KEY: ${JOB_AUTH_PUBLIC_KEY:?JOB_AUTH_PUBLIC_KEY is required} PREVIEW_AUTH_PRIVATE_KEY: ${PREVIEW_AUTH_PRIVATE_KEY:?PREVIEW_AUTH_PRIVATE_KEY is required} PREVIEW_AUTH_PUBLIC_KEY: ${PREVIEW_AUTH_PUBLIC_KEY:?PREVIEW_AUTH_PUBLIC_KEY is required} ENCRYPTION_KEY: ${ENCRYPTION_KEY:?ENCRYPTION_KEY is required} ENCRYPTION_KEY_PREVIOUS: ${ENCRYPTION_KEY_PREVIOUS:-} BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-${ENCRYPTION_KEY_PREVIOUS:-${ENCRYPTION_KEY}}} ARTIFACT_SIGNING_KEY: ${ARTIFACT_SIGNING_KEY:?ARTIFACT_SIGNING_KEY is required} ARTIFACT_SIGNING_KEY_PREVIOUS: ${ARTIFACT_SIGNING_KEY_PREVIOUS:-} DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD:?DASHBOARD_PASSWORD is required} R_APP_URL: https://${ROOMOTE_APP_DOMAIN:?ROOMOTE_APP_DOMAIN is required} R_PUBLIC_URL: https://${ROOMOTE_APP_DOMAIN:?ROOMOTE_APP_DOMAIN is required} R_INSTANCE_ID: ${R_INSTANCE_ID:-} R_SESSION_DONE_WEBHOOK_ALLOWED_PRIVATE_CIDRS: ${R_SESSION_DONE_WEBHOOK_ALLOWED_PRIVATE_CIDRS:-} R_CURATED_INTEGRATIONS_DISABLED: ${R_CURATED_INTEGRATIONS_DISABLED:-false} TRPC_URL: http://api:3001 PREVIEW_PROXY_BASE_URL: https://${ROOMOTE_PREVIEW_DOMAIN:?ROOMOTE_PREVIEW_DOMAIN is required} NEXT_PUBLIC_PREVIEW_PROXY_BASE_URL: https://${ROOMOTE_PREVIEW_DOMAIN:?ROOMOTE_PREVIEW_DOMAIN is required} PREVIEW_DOMAINS: ${ROOMOTE_PREVIEW_DOMAIN:?ROOMOTE_PREVIEW_DOMAIN is required} PREVIEW_PROXY_SUBDOMAIN_SUFFIX: ${PREVIEW_PROXY_SUBDOMAIN_SUFFIX:-} R_ALLOWED_EMAILS: ${R_ALLOWED_EMAILS:-} R_LICENSE_KEY: ${R_LICENSE_KEY:-} R_MODEL: ${R_MODEL:-} R_SMALL_MODEL: ${R_SMALL_MODEL:-} R_VISION_MODEL: ${R_VISION_MODEL:-} R_CODE_REVIEW_MODEL: ${R_CODE_REVIEW_MODEL:-} R_EXPLORE_MODEL: ${R_EXPLORE_MODEL:-} R_MODEL_ENV_KEYS: ${R_MODEL_ENV_KEYS:-} CUSTOM_PROVIDER_API_KEY: ${CUSTOM_PROVIDER_API_KEY:-} OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-} AI_GATEWAY_API_KEY: ${AI_GATEWAY_API_KEY:-} OPENAI_API_KEY: ${OPENAI_API_KEY:-} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} GOOGLE_GENERATIVE_AI_API_KEY: ${GOOGLE_GENERATIVE_AI_API_KEY:-} GEMINI_API_KEY: ${GEMINI_API_KEY:-} AWS_BEARER_TOKEN_BEDROCK: ${AWS_BEARER_TOKEN_BEDROCK:-} AWS_REGION: ${AWS_REGION:-} MOONSHOT_API_KEY: ${MOONSHOT_API_KEY:-} KIMI_API_KEY: ${KIMI_API_KEY:-} MINIMAX_API_KEY: ${MINIMAX_API_KEY:-} ZAI_API_KEY: ${ZAI_API_KEY:-} ZAI_REGION: ${ZAI_REGION:-} ZAI_CODING_PLAN_API_KEY: ${ZAI_CODING_PLAN_API_KEY:-} ZAI_CODING_PLAN_REGION: ${ZAI_CODING_PLAN_REGION:-} OPENCODE_API_KEY: ${OPENCODE_API_KEY:-} OPENCODE_GO_API_KEY: ${OPENCODE_GO_API_KEY:-} BASETEN_API_KEY: ${BASETEN_API_KEY:-} TOGETHER_API_KEY: ${TOGETHER_API_KEY:-} GITHUB_TOKEN: ${GITHUB_TOKEN:-} R_GITHUB_APP_SLUG: ${R_GITHUB_APP_SLUG:?R_GITHUB_APP_SLUG is required} R_GITHUB_ADDITIONAL_APP_SLUGS: ${R_GITHUB_ADDITIONAL_APP_SLUGS:-} R_GITHUB_APP_ID: ${R_GITHUB_APP_ID:-} R_GITHUB_APP_PRIVATE_KEY: ${R_GITHUB_APP_PRIVATE_KEY:-} R_GITHUB_CLIENT_ID: ${R_GITHUB_CLIENT_ID:-} R_GITHUB_CLIENT_SECRET: ${R_GITHUB_CLIENT_SECRET:-} R_GITHUB_WEBHOOK_SECRET: ${R_GITHUB_WEBHOOK_SECRET:-} SLACK_APP_ID: ${SLACK_APP_ID:-} R_SLACK_CLIENT_ID: ${R_SLACK_CLIENT_ID:-} R_SLACK_CLIENT_SECRET: ${R_SLACK_CLIENT_SECRET:-} R_SLACK_SIGNING_SECRET: ${R_SLACK_SIGNING_SECRET:-} R_TELEGRAM_BOT_TOKEN: ${R_TELEGRAM_BOT_TOKEN:-} R_TELEGRAM_WEBHOOK_SECRET: ${R_TELEGRAM_WEBHOOK_SECRET:-} R_DISCORD_BOT_TOKEN: ${R_DISCORD_BOT_TOKEN:-} R_DISCORD_GATEWAY_SECRET: ${R_DISCORD_GATEWAY_SECRET:-} R_LINEAR_CLIENT_ID: ${R_LINEAR_CLIENT_ID:-} R_LINEAR_CLIENT_SECRET: ${R_LINEAR_CLIENT_SECRET:-} R_LINEAR_WEBHOOK_SECRET: ${R_LINEAR_WEBHOOK_SECRET:-} DEFAULT_COMPUTE_PROVIDER: ${DEFAULT_COMPUTE_PROVIDER:?DEFAULT_COMPUTE_PROVIDER is required} MODAL_TOKEN_ID: ${MODAL_TOKEN_ID:-} MODAL_TOKEN_SECRET: ${MODAL_TOKEN_SECRET:-} MODAL_ENDPOINT: ${MODAL_ENDPOINT:-} MODAL_ENVIRONMENT: ${MODAL_ENVIRONMENT:-} MODAL_APP_NAME: ${MODAL_APP_NAME:-} MODAL_BASE_IMAGE_REF: ${MODAL_BASE_IMAGE_REF:-} MODAL_ECR_OIDC_ROLE_ARN: ${MODAL_ECR_OIDC_ROLE_ARN:-} MODAL_ECR_REGION: ${MODAL_ECR_REGION:-} MODAL_REGIONS: ${MODAL_REGIONS:-} BL_API_KEY: ${BL_API_KEY:-} BL_WORKSPACE: ${BL_WORKSPACE:-} BLAXEL_IMAGE: ${BLAXEL_IMAGE:-} BLAXEL_REGION: ${BLAXEL_REGION:-} BLAXEL_STANDBY_MAX_COUNT: ${BLAXEL_STANDBY_MAX_COUNT:-25} BLAXEL_STANDBY_MAX_AGE_HOURS: ${BLAXEL_STANDBY_MAX_AGE_HOURS:-168} BOX_API_KEY: ${BOX_API_KEY:-} BOX_API_BASE_URL: ${BOX_API_BASE_URL:-} BOX_MACHINE_TYPE: ${BOX_MACHINE_TYPE:-} BOX_TIMEOUT_MS: ${BOX_TIMEOUT_MS:-} BOX_STANDBY_MAX_COUNT: ${BOX_STANDBY_MAX_COUNT:-25} BOX_STANDBY_MAX_AGE_HOURS: ${BOX_STANDBY_MAX_AGE_HOURS:-168} AZURE_SUBSCRIPTION_ID: ${AZURE_SUBSCRIPTION_ID:-} AZURE_RESOURCE_GROUP: ${AZURE_RESOURCE_GROUP:-} AZURE_SANDBOX_GROUP: ${AZURE_SANDBOX_GROUP:-} AZURE_SANDBOX_REGION: ${AZURE_SANDBOX_REGION:-} AZURE_SANDBOX_DISK_IMAGE: ${AZURE_SANDBOX_DISK_IMAGE:-} AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-} AZURE_TENANT_ID: ${AZURE_TENANT_ID:-} AZURE_CLIENT_SECRET: ${AZURE_CLIENT_SECRET:-} AZURE_SANDBOX_REGISTRY_USERNAME: ${AZURE_SANDBOX_REGISTRY_USERNAME:-} AZURE_SANDBOX_REGISTRY_TOKEN: ${AZURE_SANDBOX_REGISTRY_TOKEN:-} AZURE_SANDBOX_SIZE: ${AZURE_SANDBOX_SIZE:-} AZURE_SANDBOX_EGRESS_INSPECTION: ${AZURE_SANDBOX_EGRESS_INSPECTION:-} AZURE_HTTP_DEBUG: ${AZURE_HTTP_DEBUG:-} DOCKER_STANDBY_MAX_COUNT: ${DOCKER_STANDBY_MAX_COUNT:-10} DOCKER_STANDBY_MAX_AGE_HOURS: ${DOCKER_STANDBY_MAX_AGE_HOURS:-24} x-roomote-production-build-args: &roomote-production-build-args R_APP_ENV: production RELEASE_VERSION: ${RELEASE_VERSION:-self-host-production} RELEASE_PRODUCT_VERSION: ${RELEASE_PRODUCT_VERSION:-} services: postgres: ports: !reset [] redis: ports: !reset [] minio: ports: !reset [] db-migrate: build: args: <<: *roomote-production-build-args environment: <<: *roomote-production-env web: environment: <<: *roomote-production-env ports: !reset [] healthcheck: test: [ 'CMD-SHELL', 'curl -fsS --max-time 2 http://127.0.0.1:3000/health >/dev/null', ] interval: 5s timeout: 3s retries: 12 start_period: 20s api: environment: <<: *roomote-production-env ports: !reset [] healthcheck: test: [ 'CMD-SHELL', 'curl -fsS --max-time 2 http://127.0.0.1:3001/health/liveness >/dev/null', ] interval: 5s timeout: 3s retries: 12 start_period: 20s controller: environment: <<: *roomote-production-env SANDBOX_OPENROUTER_API_KEY: ${SANDBOX_OPENROUTER_API_KEY:-} healthcheck: test: [ 'CMD-SHELL', 'curl -fsS --max-time 5 http://api:3001/health/controller >/dev/null', ] interval: 5s timeout: 6s retries: 12 start_period: 20s bullmq: environment: <<: *roomote-production-env ports: !reset [] healthcheck: test: [ 'CMD-SHELL', 'curl -fsS --max-time 5 http://127.0.0.1:3002/admin/health >/dev/null', ] interval: 5s timeout: 6s retries: 12 start_period: 20s preview-proxy: environment: <<: *roomote-production-env ports: !reset [] healthcheck: test: [ 'CMD-SHELL', 'curl -fsS --max-time 2 http://127.0.0.1:8081/health >/dev/null', ] interval: 5s timeout: 3s retries: 12 start_period: 20s caddy: image: caddy:2.10-alpine@sha256:4c6e91c6ed0e2fa03efd5b44747b625fec79bc9cd06ac5235a779726618e530d container_name: roomote-caddy restart: unless-stopped depends_on: web: condition: service_healthy preview-proxy: condition: service_healthy environment: ROOMOTE_APP_DOMAIN: ${ROOMOTE_APP_DOMAIN:?ROOMOTE_APP_DOMAIN is required} ROOMOTE_PREVIEW_DOMAIN: ${ROOMOTE_PREVIEW_DOMAIN:?ROOMOTE_PREVIEW_DOMAIN is required} S3_BUCKET_ARTIFACTS: ${S3_BUCKET_ARTIFACTS:-roomote-artifacts} ports: - '${CADDY_HTTP_PORT:-80}:80' - '${CADDY_HTTPS_PORT:-443}:443' volumes: - ./deploy/caddy/Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config volumes: caddy_data: caddy_config: