x-app-env: &app-env OMNARA_DATABASE_URL: postgres://omnara:omnara@postgres:5432/omnara?sslmode=disable OMNARA_REDIS_URL: redis://redis:6379/0 OMNARA_PUBLIC_URL: ${OMNARA_PUBLIC_URL:-http://localhost:8000} OMNARA_LOG_LEVEL: ${OMNARA_LOG_LEVEL:-info} OMNARA_ALLOW_INSECURE_DEV_DEFAULTS: ${OMNARA_ALLOW_INSECURE_DEV_DEFAULTS:-1} OMNARA_SECRET_ENCRYPTION_KEYS: ${OMNARA_SECRET_ENCRYPTION_KEYS:-} OMNARA_SECRET_ENCRYPTION_ACTIVE_KEY_ID: ${OMNARA_SECRET_ENCRYPTION_ACTIVE_KEY_ID:-} OMNARA_SKILL_DOWNLOAD_SIGNING_KEY: ${OMNARA_SKILL_DOWNLOAD_SIGNING_KEY:-} x-blob-env: &blob-env OMNARA_BLOB_S3_BUCKET: ${OMNARA_BLOB_S3_BUCKET:-omnara} OMNARA_BLOB_S3_REGION: ${OMNARA_BLOB_S3_REGION:-us-east-1} OMNARA_BLOB_S3_ENDPOINT: ${OMNARA_BLOB_S3_ENDPOINT:-http://rustfs:9000} OMNARA_BLOB_S3_ACCESS_KEY_ID: ${OMNARA_BLOB_S3_ACCESS_KEY_ID:-omnara} OMNARA_BLOB_S3_SECRET_ACCESS_KEY: ${OMNARA_BLOB_S3_SECRET_ACCESS_KEY:-omnara-blobs} OMNARA_BLOB_S3_USE_PATH_STYLE: ${OMNARA_BLOB_S3_USE_PATH_STYLE:-1} services: redis: image: valkey/valkey:9-alpine ports: - "${REDIS_HOST_PORT:-6379}:6379" healthcheck: test: ["CMD", "valkey-cli", "ping"] interval: 2s timeout: 2s retries: 20 postgres: image: postgres:18-alpine environment: POSTGRES_USER: omnara POSTGRES_PASSWORD: omnara POSTGRES_DB: omnara ports: - "${POSTGRES_HOST_PORT:-55432}:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U omnara -d omnara"] interval: 2s timeout: 2s retries: 20 volumes: - postgres18-data:/var/lib/postgresql rustfs: image: rustfs/rustfs:1.0.0 command: /data environment: RUSTFS_ACCESS_KEY: omnara RUSTFS_SECRET_KEY: omnara-blobs ports: - "127.0.0.1:59000:9000" healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/health/ready"] interval: 2s timeout: 2s retries: 20 volumes: - rustfs-data:/data # One-shot bucket provisioning: the application assumes buckets exist. rustfs-init: image: rustfs/rustfs:1.0.0 depends_on: rustfs: condition: service_healthy entrypoint: - /bin/sh - -ec - | curl -fsS -o /dev/null -X PUT --aws-sigv4 'aws:amz:us-east-1:s3' --user 'omnara:omnara-blobs' http://rustfs:9000/omnara curl -fsS -o /dev/null -X PUT --aws-sigv4 'aws:amz:us-east-1:s3' --user 'omnara:omnara-blobs' http://rustfs:9000/omnara-test command: [] restart: "no" # One-shot schema migration: app services depend on its successful exit and # never apply migrations themselves. migrate: profiles: ["app"] image: ghcr.io/omnara-ai/omnara-migrations:${OMNARA_RELEASE:-latest} environment: OMNARA_DATABASE_URL: postgres://omnara:omnara@postgres:5432/omnara?sslmode=disable OMNARA_MIGRATION_TIMEOUT: ${OMNARA_MIGRATION_TIMEOUT:-30m} depends_on: postgres: condition: service_healthy restart: "no" api: profiles: ["app"] image: ghcr.io/omnara-ai/omnara-api:${OMNARA_RELEASE:-latest} environment: <<: [*app-env, *blob-env] OMNARA_EMAIL_DRIVER: ${OMNARA_EMAIL_DRIVER:-console} OMNARA_EMAIL_FROM: ${OMNARA_EMAIL_FROM:-} OMNARA_SMTP_ADDR: ${OMNARA_SMTP_ADDR:-} OMNARA_SMTP_USERNAME: ${OMNARA_SMTP_USERNAME:-} OMNARA_SMTP_PASSWORD: ${OMNARA_SMTP_PASSWORD:-} OMNARA_SMTP_REQUIRE_TLS: ${OMNARA_SMTP_REQUIRE_TLS:-} SENDGRID_API_KEY: ${SENDGRID_API_KEY:-} OMNARA_AUTH_SIGNUP_ENABLED: ${OMNARA_AUTH_SIGNUP_ENABLED:-1} OMNARA_AUTH_PASSWORD_RESET_ENABLED: ${OMNARA_AUTH_PASSWORD_RESET_ENABLED:-1} OMNARA_AUTH_CONNECTORS_JSON: ${OMNARA_AUTH_CONNECTORS_JSON:-} OMNARA_TRUSTED_PROXY_CIDRS: ${OMNARA_TRUSTED_PROXY_CIDRS:-} OMNARA_BILLING_URL: ${OMNARA_BILLING_URL:-} OMNARA_DAEMON_RELEASE_URL: ${OMNARA_DAEMON_RELEASE_URL:-https://github.com/omnara-ai/omnara/releases/download/omnarad-stable} depends_on: migrate: condition: service_completed_successfully redis: condition: service_healthy rustfs-init: condition: service_completed_successfully restart: unless-stopped worker: profiles: ["app"] image: ghcr.io/omnara-ai/omnara-worker:${OMNARA_RELEASE:-latest} environment: <<: [*app-env, *blob-env] OMNARA_WORKER_EVENT_WEBHOOK_CONCURRENCY: ${OMNARA_WORKER_EVENT_WEBHOOK_CONCURRENCY:-128} OMNARA_EVENT_WEBHOOK_PER_ORG_CONCURRENCY: ${OMNARA_EVENT_WEBHOOK_PER_ORG_CONCURRENCY:-128} OMNARA_WORKER_CAPACITY: ${OMNARA_WORKER_CAPACITY:-4} OMNARA_WORKER_ASYNC_TOOL_CAPACITY: ${OMNARA_WORKER_ASYNC_TOOL_CAPACITY:-32} OMNARA_WORKER_BACKGROUND_TOOL_CAPACITY: ${OMNARA_WORKER_BACKGROUND_TOOL_CAPACITY:-8} EXA_API_KEY: ${EXA_API_KEY:-} depends_on: migrate: condition: service_completed_successfully redis: condition: service_healthy rustfs-init: condition: service_completed_successfully restart: unless-stopped maintenance: profiles: ["app"] image: ghcr.io/omnara-ai/omnara-maintenance:${OMNARA_RELEASE:-latest} environment: <<: *app-env OMNARA_MAINTENANCE_INTERVAL: ${OMNARA_MAINTENANCE_INTERVAL:-1s} depends_on: migrate: condition: service_completed_successfully redis: condition: service_healthy restart: unless-stopped web: profiles: ["app"] image: ghcr.io/omnara-ai/omnara-web:${OMNARA_RELEASE:-latest} restart: unless-stopped gateway: profiles: ["app"] image: nginxinc/nginx-unprivileged:1.29.5-alpine ports: - "${GATEWAY_HOST_PORT:-8000}:8080" volumes: - ./gateway.nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: api: condition: service_started web: condition: service_started restart: unless-stopped volumes: postgres18-data: rustfs-data: networks: default: name: omnara-control-plane