[variables]
main_domain = "${domain}"

[config]
env = [
  # =============================================================================
  # 🌐 CORE DOMAIN CONFIGURATION
  # =============================================================================
  "FQDN=${main_domain}",
  "SCHEME=https",
  "WS_SCHEME=wss",
  "APPFLOWY_BASE_URL=https://${main_domain}",
  "APPFLOWY_WEBSOCKET_BASE_URL=wss://${main_domain}/ws/v2",
  "APPFLOWY_WEB_URL=https://${main_domain}",
  "API_EXTERNAL_URL=https://${main_domain}/gotrue",
  "TZ=UTC",

  # Admin Configuration
  "GOTRUE_ADMIN_EMAIL=${email}",
  "GOTRUE_ADMIN_PASSWORD=${password:16}",
  "GOTRUE_DISABLE_SIGNUP=false",

  # =============================================================================
  # 🗄️ DATABASE & CACHE CONFIGURATION
  # =============================================================================
  "POSTGRES_HOST=postgres",
  "POSTGRES_USER=appflowy",
  "POSTGRES_PASSWORD=${password:64}",
  "POSTGRES_PORT=5432",
  "POSTGRES_DB=appflowy",
  "REDIS_HOST=redis",
  "REDIS_PORT=6379",

  # =============================================================================
  # 🔐 GOTRUE AUTHENTICATION CONFIGURATION
  # =============================================================================

  # JWT Configuration
  "GOTRUE_JWT_SECRET=${password:64}",
  "GOTRUE_JWT_EXP=7200",
  "GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin",

  # Database Configuration
  "GOTRUE_DB_DRIVER=postgres",
  "GOTRUE_DATABASE_URL=postgres://appflowy:${POSTGRES_PASSWORD}@postgres:5432/appflowy?search_path=auth",
  "PORT=9999",

  # Site Configuration
  "GOTRUE_SITE_URL=appflowy-flutter://",
  "GOTRUE_URI_ALLOW_LIST=**",

  # Email Configuration (SMTP - Configure for production)
  "GOTRUE_SMTP_HOST=",
  "GOTRUE_SMTP_PORT=465",
  "GOTRUE_SMTP_USER=",
  "GOTRUE_SMTP_PASS=",
  "GOTRUE_SMTP_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}",
  "GOTRUE_SMTP_MAX_FREQUENCY=1ns",
  "GOTRUE_RATE_LIMIT_EMAIL_SENT=100",
  "GOTRUE_MAILER_AUTOCONFIRM=true",

  # Email Templates
  "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_MAILER_TEMPLATES_MAGIC_LINK=",

  # OAuth Providers (Configure as needed)
  "GOTRUE_EXTERNAL_GOOGLE_ENABLED=false",
  "GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=",
  "GOTRUE_EXTERNAL_GOOGLE_SECRET=",
  "GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI=https://${main_domain}/gotrue/callback",

  "GOTRUE_EXTERNAL_GITHUB_ENABLED=false",
  "GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=",
  "GOTRUE_EXTERNAL_GITHUB_SECRET=",
  "GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI=https://${main_domain}/gotrue/callback",

  "GOTRUE_EXTERNAL_DISCORD_ENABLED=false",
  "GOTRUE_EXTERNAL_DISCORD_CLIENT_ID=",
  "GOTRUE_EXTERNAL_DISCORD_SECRET=",
  "GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI=https://${main_domain}/gotrue/callback",

  # SAML Configuration
  "GOTRUE_SAML_ENABLED=false",
  "GOTRUE_SAML_PRIVATE_KEY=",

  # =============================================================================
  # ☁️ APPFLOWY CLOUD SERVICE CONFIGURATION
  # =============================================================================
  # Core Configuration
  "RUST_LOG=info",
  "APPFLOWY_ENVIRONMENT=production",
  "APPFLOWY_DATABASE_URL=postgres://appflowy:${POSTGRES_PASSWORD}@postgres:5432/appflowy",
  "APPFLOWY_REDIS_URI=redis://redis:6379",

  # Authentication Integration
  "APPFLOWY_GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}",
  "APPFLOWY_GOTRUE_JWT_EXP=7200",
  "APPFLOWY_GOTRUE_BASE_URL=http://gotrue:9999",

  # Access Control and Performance
  "APPFLOWY_ACCESS_CONTROL=true",
  "APPFLOWY_DATABASE_MAX_CONNECTIONS=40",
  "APPFLOWY_WEBSOCKET_MAILBOX_SIZE=6000",

  # Email Configuration (SMTP)
  "APPFLOWY_MAILER_SMTP_HOST=",
  "APPFLOWY_MAILER_SMTP_PORT=465",
  "APPFLOWY_MAILER_SMTP_USERNAME=",
  "APPFLOWY_MAILER_SMTP_EMAIL=",
  "APPFLOWY_MAILER_SMTP_PASSWORD=",
  "APPFLOWY_MAILER_SMTP_TLS_KIND=wrapper",

  # =============================================================================
  # 💾 FILE STORAGE CONFIGURATION (MinIO/S3)
  # =============================================================================
  # MinIO Configuration
  "MINIO_HOST=minio",
  "MINIO_PORT=9000",
  "APPFLOWY_S3_USE_MINIO=true",
  "APPFLOWY_S3_CREATE_BUCKET=true",
  "APPFLOWY_S3_MINIO_URL=http://minio:9000",

  # Storage Credentials
  "APPFLOWY_S3_ACCESS_KEY=${password:16}",
  "APPFLOWY_S3_SECRET_KEY=${password:32}",

  # Storage Configuration
  "APPFLOWY_S3_BUCKET=appflowy",
  "APPFLOWY_S3_REGION=us-east-1",
  "APPFLOWY_S3_PRESIGNED_URL_ENDPOINT=https://${main_domain}/minio-api",

  # AWS S3 Configuration (Alternative to MinIO)
  # "APPFLOWY_S3_USE_MINIO=false",
  # "APPFLOWY_S3_REGION=us-east-1",

  # =============================================================================
  # 🎛️ ADMIN FRONTEND CONFIGURATION
  # =============================================================================
  "ADMIN_FRONTEND_REDIS_URL=redis://redis:6379",
  "ADMIN_FRONTEND_GOTRUE_URL=http://gotrue:9999",
  "ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=http://appflowy_cloud:8000",
  "ADMIN_FRONTEND_PATH_PREFIX=/console",

  # =============================================================================
  # 🤖 AI FEATURES CONFIGURATION (Optional)
  # =============================================================================
  # OpenAI Configuration
  "AI_OPENAI_API_KEY=",
  "DEFAULT_AI_MODEL=gpt-4o-mini",
  "DEFAULT_AI_COMPLETION_MODEL=gpt-4o-mini",

  # Azure OpenAI (Alternative)
  "AZURE_OPENAI_API_KEY=",
  "AZURE_OPENAI_ENDPOINT=",
  "AZURE_OPENAI_API_VERSION=",

  # AI Service Configuration
  "AI_SERVER_HOST=ai",
  "AI_SERVER_PORT=5001",
  "AI_DATABASE_URL=postgresql+psycopg://appflowy:${POSTGRES_PASSWORD}@postgres:5432/appflowy",
  "AI_REDIS_URL=redis://redis:6379",
  "AI_USE_MINIO=true",
  "AI_MINIO_URL=http://minio:9000",
  "AI_APPFLOWY_HOST=https://${main_domain}",

  # Embedding Configuration
  "APPFLOWY_EMBEDDING_CHUNK_SIZE=2000",
  "APPFLOWY_EMBEDDING_CHUNK_OVERLAP=200",

  # =============================================================================
  # ⚙️ WORKER SERVICES CONFIGURATION
  # =============================================================================
  # AppFlowy Worker
  "APPFLOWY_WORKER_REDIS_URL=redis://redis:6379",
  "APPFLOWY_WORKER_ENVIRONMENT=production",
  "APPFLOWY_WORKER_DATABASE_URL=postgres://appflowy:${POSTGRES_PASSWORD}@postgres:5432/appflowy",
  "APPFLOWY_WORKER_DATABASE_NAME=appflowy",
  "APPFLOWY_WORKER_IMPORT_TICK_INTERVAL=30",

  # Indexer Configuration
  "APPFLOWY_INDEXER_ENABLED=true",
  "APPFLOWY_INDEXER_DATABASE_URL=postgres://appflowy:${POSTGRES_PASSWORD}@postgres:5432/appflowy",
  "APPFLOWY_INDEXER_REDIS_URL=redis://redis:6379",
  "APPFLOWY_INDEXER_EMBEDDING_BUFFER_SIZE=5000",

  # Collaboration Service
  "APPFLOWY_COLLABORATE_MULTI_THREAD=false",
  "APPFLOWY_COLLABORATE_REMOVE_BATCH_SIZE=100",

  # =============================================================================
  # 🌐 NGINX CONFIGURATION
  # =============================================================================
  "NGINX_PORT=80",
  "NGINX_TLS_PORT=443",

  # =============================================================================
  # 🛠️ VERSION TAGS (Easily Configurable)
  # =============================================================================
  "GOTRUE_VERSION=latest",
  "APPFLOWY_CLOUD_VERSION=latest",
  "APPFLOWY_ADMIN_FRONTEND_VERSION=latest",
  "APPFLOWY_AI_VERSION=latest",
  "APPFLOWY_WORKER_VERSION=latest",
  "APPFLOWY_WEB_VERSION=latest",
]

[[config.domains]]
serviceName = "nginx"
port = 80
host = "${main_domain}"


[[config.mounts]]
filePath = "/nginx/nginx.conf"
content = """# Minimal nginx configuration for AppFlowy-Cloud
# Self Hosted AppFlowy Cloud user should alter this file to suit their needs,
# or use the appflowy.site.conf in external_proxy_config/nginx if they are using
# an external proxy.

events {
    worker_connections 1024;
}

http {
    # docker dns resolver
    resolver 127.0.0.11 valid=10s;
    #error_log /var/log/nginx/error.log debug;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    map $http_origin $cors_origin {
        # AppFlowy Web origin
        "~^http://localhost:3000$" $http_origin;
        default "null";
    }

    server {
        listen 8080;

        # https://github.com/nginxinc/nginx-prometheus-exporter
        location = /stub_status {
            stub_status;
        }
    }


    server {

        listen 80;
        client_max_body_size 10M;

        underscores_in_headers on;
        set $appflowy_cloud_backend "http://appflowy_cloud:8000";
        set $gotrue_backend "http://gotrue:9999";
        set $admin_frontend_backend "http://admin_frontend:3000";
        set $appflowy_web_backend "http://appflowy_web:80";
        set $minio_backend "http://minio:9001";
        set $minio_api_backend "http://minio:9000";
        # Host name for minio, used internally within docker compose
        set $minio_internal_host "minio:9000";
        set $pgadmin_backend "http://pgadmin:80";

        # GoTrue
        location /gotrue/ {
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' $cors_origin always;
                add_header 'Access-Control-Allow-Credentials' 'true' always;
                add_header 'Access-Control-Allow-Headers' '*' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
                add_header 'Access-Control-Max-Age' 3600 always;
                add_header 'Content-Type' 'text/plain charset=UTF-8' always;
                add_header 'Content-Length' 0 always;
                return 204;
            }

            proxy_pass $gotrue_backend;

            rewrite ^/gotrue(/.*)$ $1 break;

            # Allow headers like redirect_to to be handed over to the gotrue
            # for correct redirecting
            proxy_set_header Host $http_host;
            proxy_pass_request_headers on;
        }

        # WebSocket
        location /ws {
            proxy_pass $appflowy_cloud_backend;

            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
            proxy_read_timeout 86400s;
        }

        location /api {
            proxy_pass $appflowy_cloud_backend;
            proxy_set_header X-Request-Id $request_id;
            proxy_set_header Host $http_host;

            # Set CORS headers for other requests
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' $cors_origin always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always;
                add_header 'Access-Control-Max-Age' 3600 always;
                return 204;
            }

            add_header 'Access-Control-Allow-Origin' $cors_origin always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always;
            add_header 'Access-Control-Max-Age' 3600 always;

            location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ {
                proxy_pass $appflowy_cloud_backend;
                proxy_request_buffering off;
                client_max_body_size 256M;
                if ($request_method = 'OPTIONS') {
                    add_header 'Access-Control-Allow-Origin' $cors_origin always;
                    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
                    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always;
                    add_header 'Access-Control-Max-Age' 3600 always;
                    return 204;
                }

                add_header 'Access-Control-Allow-Origin' $cors_origin always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always;
                add_header 'Access-Control-Max-Age' 3600 always;
            }

            # AppFlowy-Cloud
            location /api/chat {
                proxy_pass $appflowy_cloud_backend;

                proxy_http_version 1.1;
                proxy_set_header Connection "";
                chunked_transfer_encoding on;
                proxy_buffering off;
                proxy_cache off;

                proxy_read_timeout 600s;
                proxy_connect_timeout 600s;
                proxy_send_timeout 600s;
            }

            location /api/import {
                proxy_pass $appflowy_cloud_backend;

                # Set headers
                proxy_set_header X-Request-Id $request_id;
                proxy_set_header Host $http_host;

                # Handle CORS
                add_header 'Access-Control-Allow-Origin' $cors_origin always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Device-Id' always;
                add_header 'Access-Control-Max-Age' 3600 always;

                # Timeouts
                proxy_read_timeout 600s;
                proxy_connect_timeout 600s;
                proxy_send_timeout 600s;

                # Disable buffering for large file uploads
                proxy_request_buffering off;
                proxy_buffering off;
                proxy_cache off;
                client_max_body_size 2G;
            }
        }

        # Minio Web UI
        # Derive from: https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html
        # Optional Module, comment this section if you did not deploy minio in docker-compose.yml
        # This endpoint is meant to be used for the MinIO Web UI, accessible via the admin portal
        location /minio/ {
            proxy_pass $minio_backend;

            rewrite ^/minio/(.*) /$1 break;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-NginX-Proxy true;

            ## This is necessary to pass the correct IP to be hashed
            real_ip_header X-Real-IP;

            proxy_connect_timeout 300s;

            ## To support websockets in MinIO versions released after January 2023
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
            # Uncomment the following line to set the Origin request to an empty string
            # proxy_set_header Origin '';

            chunked_transfer_encoding off;
        }

        # Optional Module, comment this section if you did not deploy minio in docker-compose.yml
        # This is used for presigned url, which is needs to be exposed to the AppFlowy client application.
        location /minio-api/ {
            proxy_pass $minio_api_backend;

            # Set the host to internal host because the presigned url was signed against the internal host
            proxy_set_header Host $minio_internal_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            rewrite ^/minio-api/(.*) /$1 break;

            proxy_connect_timeout 300s;
            # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;
        }

        # PgAdmin
        # Optional Module, comment this section if you did not deploy pgadmin in docker-compose.yml
        location /pgadmin/ {
            set $pgadmin pgadmin;
            proxy_pass $pgadmin_backend;

            proxy_set_header X-Script-Name /pgadmin;
            proxy_set_header X-Scheme $scheme;
            proxy_set_header Host $host;
            proxy_redirect off;
        }

        # Admin Frontend
        # Optional Module, comment this section if you did not deploy admin_frontend in docker-compose.yml
        location /console {
            proxy_pass $admin_frontend_backend;

            proxy_set_header X-Scheme $scheme;
            proxy_set_header Host $host;
        }

        # AppFlowy Web
        location / {
            proxy_pass $appflowy_web_backend;
            proxy_set_header X-Scheme $scheme;
            proxy_set_header Host $host;
        }
    }

}
"""
