# Essential services for AppFlowy Cloud

services:
  nginx:
    restart: on-failure
    image: nginx
    ports:
      - ${NGINX_PORT:-80}:80   # Disable this if you are using TLS
      - ${NGINX_TLS_PORT:-443}:443
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/ssl/certificate.crt:/etc/nginx/ssl/certificate.crt
      - ./nginx/ssl/private_key.key:/etc/nginx/ssl/private_key.key
    networks:
      - shared_network
      #- ./nginx_logs:/var/log/nginx

  # You do not need this if you have configured to use your own s3 file storage
  # You can try to access http://localhost/minio/browser/appflowy in your browser
  minio:
    restart: on-failure
    image: minio/minio
    ports:
      - 9000:9000
      - 9001:9001
    environment:
      - MINIO_BROWSER_REDIRECT_URL=http://localhost/minio
      - MINIO_ROOT_USER=${APPFLOWY_S3_ACCESS_KEY:-minioadmin}
      - MINIO_ROOT_PASSWORD=${APPFLOWY_S3_SECRET_KEY:-minioadmin}
    command: server /data --console-address ":9001"
    volumes:
      - minio_data:/data
    networks:
      - shared_network

  postgres:
    restart: on-failure
    image: pgvector/pgvector:pg15
    healthcheck:
      test: [ "CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}", "-p", "${POSTGRES_PORT:-5432}" ]
      interval: 5s
      timeout: 5s
      retries: 6
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_DB=${POSTGRES_DB:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}
      - POSTGRES_HOST=${POSTGRES_HOST:-postgres}
      - PGPORT=${POSTGRES_PORT:-5432}
    command: ["postgres", "-c", "port=${POSTGRES_PORT:-5432}"]
    networks:
      - shared_network

  redis:
    restart: on-failure
    image: redis
    ports:
      - "6379:6379"
    networks:
      - shared_network

  gotrue:
    restart: on-failure
    image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: "curl --fail http://127.0.0.1:9999/health || exit 1"
      interval: 5s
      timeout: 5s
      retries: 12
    environment:
      # There are a lot of options to configure GoTrue. You can reference the example config:
      # https://github.com/supabase/auth/blob/master/example.env
      - GOTRUE_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}
      - GOTRUE_ADMIN_PASSWORD=${GOTRUE_ADMIN_PASSWORD}
      - GOTRUE_DISABLE_SIGNUP=${GOTRUE_DISABLE_SIGNUP:-false}
      - GOTRUE_SITE_URL=appflowy-flutter://                           # redirected to AppFlowy application
      - GOTRUE_URI_ALLOW_LIST=**                                      # adjust restrict if necessary
      - GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}                        # authentication secret
      - GOTRUE_JWT_EXP=${GOTRUE_JWT_EXP}
      # Without this environment variable, the createuser command will create an admin
      # with the `admin` role as opposed to `supabase_admin`
      - GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin
      - GOTRUE_DB_DRIVER=postgres
      - API_EXTERNAL_URL=${API_EXTERNAL_URL}
      - DATABASE_URL=${GOTRUE_DATABASE_URL}
      - PORT=9999
      - GOTRUE_SMTP_HOST=${GOTRUE_SMTP_HOST}                          # e.g. smtp.gmail.com
      - GOTRUE_SMTP_PORT=${GOTRUE_SMTP_PORT}                          # e.g. 465
      - GOTRUE_SMTP_USER=${GOTRUE_SMTP_USER}                          # email sender, e.g. noreply@appflowy.io
      - GOTRUE_SMTP_PASS=${GOTRUE_SMTP_PASS}                          # email password
      - GOTRUE_MAILER_URLPATHS_CONFIRMATION=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_INVITE=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_RECOVERY=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=/gotrue/verify
      - GOTRUE_SMTP_ADMIN_EMAIL=${GOTRUE_SMTP_ADMIN_EMAIL}                # email with admin privileges e.g. internal@appflowy.io
      - GOTRUE_SMTP_MAX_FREQUENCY=${GOTRUE_SMTP_MAX_FREQUENCY:-1ns}       # set to 1ns for running tests
      - GOTRUE_RATE_LIMIT_EMAIL_SENT=${GOTRUE_RATE_LIMIT_EMAIL_SENT:-100} # number of email sendable per minute
      - GOTRUE_MAILER_AUTOCONFIRM=${GOTRUE_MAILER_AUTOCONFIRM:-false}     # change this to true to skip email confirmation
      # Google OAuth config
      - GOTRUE_EXTERNAL_GOOGLE_ENABLED=${GOTRUE_EXTERNAL_GOOGLE_ENABLED}
      - GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=${GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID}
      - GOTRUE_EXTERNAL_GOOGLE_SECRET=${GOTRUE_EXTERNAL_GOOGLE_SECRET}
      - GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI=${GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI}
      # GITHUB OAuth config
      - GOTRUE_EXTERNAL_GITHUB_ENABLED=${GOTRUE_EXTERNAL_GITHUB_ENABLED}
      - GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=${GOTRUE_EXTERNAL_GITHUB_CLIENT_ID}
      - GOTRUE_EXTERNAL_GITHUB_SECRET=${GOTRUE_EXTERNAL_GITHUB_SECRET}
      - GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI=${GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI}
      # Discord OAuth config
      - GOTRUE_EXTERNAL_DISCORD_ENABLED=${GOTRUE_EXTERNAL_DISCORD_ENABLED}
      - GOTRUE_EXTERNAL_DISCORD_CLIENT_ID=${GOTRUE_EXTERNAL_DISCORD_CLIENT_ID}
      - GOTRUE_EXTERNAL_DISCORD_SECRET=${GOTRUE_EXTERNAL_DISCORD_SECRET}
      - GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI=${GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI}
    networks:
      - shared_network

  appflowy_cloud:
    restart: on-failure
    ports:
      - 8000:8000
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - APPFLOWY_ENVIRONMENT=production
      - APPFLOWY_DATABASE_URL=${APPFLOWY_DATABASE_URL}
      - APPFLOWY_REDIS_URI=${APPFLOWY_REDIS_URI}
      - APPFLOWY_GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}
      - APPFLOWY_GOTRUE_BASE_URL=${APPFLOWY_GOTRUE_BASE_URL}
      - APPFLOWY_S3_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - APPFLOWY_S3_MINIO_URL=${APPFLOWY_S3_MINIO_URL}
      - APPFLOWY_S3_ACCESS_KEY=${APPFLOWY_S3_ACCESS_KEY}
      - APPFLOWY_S3_SECRET_KEY=${APPFLOWY_S3_SECRET_KEY}
      - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET}
      - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION}
      - APPFLOWY_ACCESS_CONTROL=${APPFLOWY_ACCESS_CONTROL}
      # For the CI testing, we set the database connection to 20. The default value is 40.
      - APPFLOWY_DATABASE_MAX_CONNECTIONS=20
      - AI_SERVER_HOST=${AI_SERVER_HOST}
      - AI_SERVER_PORT=${AI_SERVER_PORT}
      - APPFLOWY_WEB_URL=${APPFLOWY_WEB_URL}
      - APPFLOWY_MAILER_SMTP_HOST=${APPFLOWY_MAILER_SMTP_HOST}
      - APPFLOWY_MAILER_SMTP_PORT=${APPFLOWY_MAILER_SMTP_PORT}
      - APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME}
      - APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL}
      - APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD}
      - AI_OPENAI_API_KEY=${AI_OPENAI_API_KEY}
      - APPFLOWY_SEARCH_SERVICE_URL=${APPFLOWY_SEARCH_SERVICE_URL:-http://appflowy_search:4002}
      - APPFLOWY_SEARCH_REQUEST_TIMEOUT_SECS=${APPFLOWY_SEARCH_REQUEST_TIMEOUT_SECS:-10}
    build:
      context: .
      dockerfile: Dockerfile
      args:
        FEATURES: ""
        PROFILE: ci
    networks:
      - shared_network
    image: appflowyinc/appflowy_cloud:${APPFLOWY_CLOUD_VERSION:-latest}
    depends_on:
      gotrue:
        condition: service_healthy
      appflowy_search:
        condition: service_started

  admin_frontend:
    restart: on-failure
    build:
      context: .
      dockerfile: ./admin_frontend/Dockerfile
    image: appflowyinc/admin_frontend:${APPFLOWY_ADMIN_FRONTEND_VERSION:-latest}
    ports:
      - 3000:3000
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
      - ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
      - ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
      - ADMIN_FRONTEND_PATH_PREFIX=${ADMIN_FRONTEND_PATH_PREFIX:-}
    networks:
      - shared_network
    depends_on:
      gotrue:
        condition: service_healthy
      appflowy_cloud:
        condition: service_started

  ai:
    restart: on-failure
    image: appflowyinc/appflowy_ai_premium:${APPFLOWY_AI_VERSION:-latest}
    ports:
      - "5001:5001"
    environment:
      - OPENAI_API_KEY=${AI_OPENAI_API_KEY}
      - AI_AWS_ACCESS_KEY_ID=${APPFLOWY_S3_ACCESS_KEY}
      - AI_AWS_SECRET_ACCESS_KEY=${APPFLOWY_S3_SECRET_KEY}
      - AI_APPFLOWY_BUCKET_NAME=${AI_APPFLOWY_BUCKET_NAME}
      - AI_SERVER_PORT=${AI_SERVER_PORT}
      - AI_DATABASE_URL=${AI_DATABASE_URL}
      - AI_REDIS_URL=${AI_REDIS_URL}
      - AI_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - AI_MINIO_URL=${AI_MINIO_URL}
      - AI_APPFLOWY_HOST=${AI_APPFLOWY_HOST}
      - SUPPORT_OPENAI_V3_IMAGE_MODEL=false
      - LOG_LEVEL=DEBUG
    networks:
      - shared_network

  appflowy_worker:
    restart: on-failure
    image: appflowyinc/appflowy_worker:${APPFLOWY_WORKER_VERSION:-latest}
    build:
      context: .
      dockerfile: ./services/appflowy-worker/Dockerfile
    ports:
      - "4001:4001"
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - APPFLOWY_WORKER_REDIS_URL=${APPFLOWY_WORKER_REDIS_URL:-redis://redis:6379}
      - APPFLOWY_WORKER_ENVIRONMENT=production
      - APPFLOWY_WORKER_DATABASE_URL=${APPFLOWY_WORKER_DATABASE_URL}
      - APPFLOWY_WORKER_DATABASE_NAME=${APPFLOWY_WORKER_DATABASE_NAME}
      - APPFLOWY_S3_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - APPFLOWY_S3_MINIO_URL=${APPFLOWY_S3_MINIO_URL}
      - APPFLOWY_S3_ACCESS_KEY=${APPFLOWY_S3_ACCESS_KEY}
      - APPFLOWY_S3_SECRET_KEY=${APPFLOWY_S3_SECRET_KEY}
      - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET}
      - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION}
      - APPFLOWY_MAILER_SMTP_HOST=${APPFLOWY_MAILER_SMTP_HOST}
      - APPFLOWY_MAILER_SMTP_PORT=${APPFLOWY_MAILER_SMTP_PORT}
      - APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME}
      - APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL}
      - APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD}
    networks:
      - shared_network

  appflowy_search:
    restart: on-failure
    image: appflowyinc/appflowy_search:${APPFLOWY_SEARCH_VERSION:-latest}
    ports:
      - "4002:4002"
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - APPFLOWY_SEARCH_HOST=${APPFLOWY_SEARCH_HOST:-[::]}
      - APPFLOWY_SEARCH_PORT=${APPFLOWY_SEARCH_PORT:-4002}
      - APPFLOWY_SEARCH_DATABASE_URL=${APPFLOWY_DATABASE_URL}
      - APPFLOWY_SEARCH_REDIS_URL=${APPFLOWY_REDIS_URI}
      - AI_OPENAI_API_KEY=${AI_OPENAI_API_KEY}
      - AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY}
      - AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT}
      - AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION}
      - APPFLOWY_BACKGROUND_INDEXER_ENABLED=true
      - APPFLOWY_INDEXER_DATABASE_ENABLED=${APPFLOWY_INDEXER_DATABASE_ENABLED:-false}
      - APPFLOWY_KEYWORD_SEARCH_ENABLED=${APPFLOWY_KEYWORD_SEARCH_ENABLED:-false}
      - APPFLOWY_KEYWORD_WORKER_ENABLED=true
      - APPFLOWY_KEYWORD_INDEX_MAP_SIZE_BYTES=${APPFLOWY_KEYWORD_INDEX_MAP_SIZE_BYTES:-0}
      - APPFLOWY_KEYWORD_INDEX_DIR=${APPFLOWY_KEYWORD_INDEX_DIR:-/var/lib/appflowy/keyword_index}
      - APPFLOWY_GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}
    volumes:
      - keyword_index_data:/var/lib/appflowy/keyword_index
    networks:
      - shared_network
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  minio_data:
  keyword_index_data:

networks:
  shared_network:
    name: appflowy_network
    driver: bridge
