version: '3.8' x-environment: &shared-environment # ---- APP ------- VERSION: ${VERSION} APP_NAME: ${APP_NAME} APP_ENV: ${APP_ENV:-development} NODE_ENV: ${APP_ENV:-development} HOST: ${HOST} VERIFY_EMAIL_ENABLED: ${VERIFY_EMAIL_ENABLED:-false} EDITION: ${EDITION:-community} # ---- REDIS ---- REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} # ---- DATABASE ---- DB_TYPE: ${DB_TYPE:-postgres} DB_HOST: ${PGBOUNCER_HOST:-pgbouncer} DB_PORT: ${PGBOUNCER_PORT:-6432} DB_NAME: server DB_NAME_HOCUSPOCUS: ${DB_NAME_HOCUSPOCUS:-server} DB_USER_HOCUSPOCUS: ${DB_USER_HOCUSPOCUS:-app_user} DB_NAME_SERVER: server DB_USER_SERVER: app_user DB_USER_ADMIN: ${DB_USER_ADMIN:-postgres} POSTGRES_USER: postgres # ---- LOGGING ---- LOG_LEVEL: ${LOG_LEVEL:-INFO} LOG_IS_FORMAT_JSON: ${LOG_IS_FORMAT_JSON:-false} LOG_IS_FULL_DETAILS: ${LOG_IS_FULL_DETAILS:-false} LOG_ENABLED_FILE_LOGGING: ${LOG_ENABLED_FILE_LOGGING} LOG_DIR_PATH: ${LOG_DIR_PATH} LOG_ENABLED_EXTERNAL_LOGGING: ${LOG_ENABLED_EXTERNAL_LOGGING} LOG_EXTERNAL_HTTP_HOST: ${LOG_EXTERNAL_HTTP_HOST} LOG_EXTERNAL_HTTP_PORT: ${LOG_EXTERNAL_HTTP_PORT} LOG_EXTERNAL_HTTP_PATH: ${LOG_EXTERNAL_HTTP_PATH} LOG_EXTERNAL_HTTP_LEVEL: ${LOG_EXTERNAL_HTTP_LEVEL} LOG_EXTERNAL_HTTP_TOKEN: ${LOG_EXTERNAL_HTTP_TOKEN} # ---- HOCUSPOCUS ---- HOCUSPOCUS_PORT: ${HOCUSPOCUS_PORT} HOCUSPOCUS_URL: ${HOCUSPOCUS_URL} REQUIRE_HOCUSPOCUS: ${REQUIRE_HOCUSPOCUS:-false} # ---- EMAIL ---- EMAIL_ENABLE: ${EMAIL_ENABLE:-false} EMAIL_FROM: ${EMAIL_FROM:-noreply@example.com} EMAIL_HOST: ${EMAIL_HOST} EMAIL_PORT: ${EMAIL_PORT:-587} EMAIL_USERNAME: ${EMAIL_USERNAME:-noreply@example.com} # ---- CRYPTO ---- CRYPTO_SALT_BYTES: ${SALT_BYTES} CRYPTO_ITERATION: ${ITERATION} CRYPTO_KEY_LENGTH: ${KEY_LENGTH} CRYPTO_ALGORITHM: ${ALGORITHM} # ---- TOKEN ---- TOKEN_EXPIRES: ${TOKEN_EXPIRES} # ---- AI / LLM ---- OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-} OPENROUTER_API: ${OPENROUTER_API:-} # ---- AUTH ---- NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000} # Required for edge auth initialization (NextAuth secret must be present in env, not only as a Docker secret file) NEXTAUTH_SECRET: ${NEXTAUTH_SECRET} NEXTAUTH_SESSION_EXPIRES: ${NEXTAUTH_SESSION_EXPIRES:-86400} # ---- SECRET PROVIDER ---- # Composite secret provider configuration # Default: env -> filesystem chain for reads, filesystem for writes # Override these in production for vault integration SECRET_READ_CHAIN: ${SECRET_READ_CHAIN:-env,filesystem} SECRET_WRITE_PROVIDER: ${SECRET_WRITE_PROVIDER:-filesystem} # ---- DEPLOY INFO ---- PROJECT_NAME: ${PROJECT_NAME} EXPOSE_DB_PORT: ${EXPOSE_DB_PORT:-5432} EXPOSE_HOCUSPOCUS_PORT: ${EXPOSE_HOCUSPOCUS_PORT:-1234} EXPOSE_REDIS_PORT: ${EXPOSE_REDIS_PORT:-6379} EXPOSE_SERVER_PORT: ${EXPOSE_SERVER_PORT:-3000} secrets: db_password_server: file: ./secrets/db_password_server db_password_hocuspocus: file: ./secrets/db_password_hocuspocus postgres_password: file: ./secrets/postgres_password redis_password: file: ./secrets/redis_password email_password: file: ./secrets/email_password crypto_key: file: ./secrets/crypto_key token_secret_key: file: ./secrets/token_secret_key nextauth_secret: file: ./secrets/nextauth_secret google_oauth_client_id: file: ./secrets/google_oauth_client_id google_oauth_client_secret: file: ./secrets/google_oauth_client_secret alga_auth_key: file: ./secrets/alga_auth_key ninjaone_client_id: file: ./secrets/ninjaone_client_id ninjaone_client_secret: file: ./secrets/ninjaone_client_secret services: server: extends: file: ./server/docker-compose.yaml service: server container_name: ${APP_NAME:-sebastian}_server networks: - app-network environment: <<: *shared-environment volumes: - type: bind source: ./secrets/db_password_server target: /run/secrets/db_password_server read_only: true - type: bind source: ./secrets/tenants target: /run/secrets/tenants # ngrok volume for webhook URL syncing (only mounted with docker-compose.ngrok.yaml) - ngrok-data:/app/ngrok:ro secrets: - postgres_password - db_password_server - db_password_hocuspocus - redis_password - email_password - crypto_key - token_secret_key - nextauth_secret - google_oauth_client_id - google_oauth_client_secret - alga_auth_key depends_on: postgres: condition: service_started pgbouncer: condition: service_started redis: condition: service_started hocuspocus: condition: service_started required: false setup: condition: service_completed_successfully setup: build: context: . dockerfile: setup/Dockerfile args: SERVER_IMAGE_REPO: ${ALGA_SETUP_IMAGE_REPO:-ghcr.io/nine-minds/alga-psa-ce} ALGA_IMAGE_TAG: ${ALGA_IMAGE_TAG:-latest} # The setup image uses a prebuilt base image that is published as amd64-only. platform: linux/amd64 networks: - app-network environment: <<: *shared-environment DB_HOST: ${DB_HOST:-postgres} DB_PORT: ${DB_PORT:-5432} NODE_OPTIONS: --experimental-vm-modules volumes: - type: bind source: ./secrets/postgres_password target: /run/secrets/postgres_password read_only: true - type: bind source: ./secrets/db_password_server target: /run/secrets/db_password_server read_only: true secrets: - postgres_password - db_password_server entrypoint: ["/opt/setup/entrypoint.sh"] depends_on: postgres: condition: service_started hocuspocus: extends: file: ./hocuspocus/docker-compose.yaml service: hocuspocus container_name: ${APP_NAME:-sebastian}_hocuspocus networks: - app-network environment: <<: *shared-environment secrets: - db_password_hocuspocus - redis_password depends_on: redis: condition: service_started postgres: image: pgvector/pgvector:0.8.0-pg15 container_name: ${APP_NAME:-sebastian}_postgres networks: - app-network environment: <<: *shared-environment POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password secrets: - postgres_password ports: - "${EXPOSE_DB_PORT:-5432}:5432" redis: image: 'resend-custom-domains-redis:latest' container_name: ${APP_NAME:-sebastian}_redis entrypoint: ["/app/redis/entrypoint.sh"] networks: - app-network environment: <<: *shared-environment secrets: - redis_password ports: - '${EXPOSE_REDIS_PORT:-6379}:6379' networks: app-network: driver: bridge volumes: # Used by docker-compose.ngrok.yaml, but referenced in the base server definition. ngrok-data: