{ "metrics": { "enabled": { "type": "Boolean", "desc": "Enable metric and tracing collection" } }, "crypto": { "privateKey": { "type": "String", "desc": "The private key for used by the crypto module to create signed tokens or encrypt data.", "env": "AFFINE_PRIVATE_KEY" } }, "job": { "queue": { "type": "Object", "desc": "The config for job queues", "link": "https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html" }, "worker": { "type": "Object", "desc": "The config for job workers", "link": "https://api.docs.bullmq.io/interfaces/v5.WorkerOptions.html" }, "queues.copilot": { "type": "Object", "desc": "The config for copilot job queue" }, "queues.calendar": { "type": "Object", "desc": "The config for calendar job queue" }, "queues.doc": { "type": "Object", "desc": "The config for doc job queue" }, "queues.indexer": { "type": "Object", "desc": "The config for indexer job queue" }, "queues.notification": { "type": "Object", "desc": "The config for notification job queue" }, "queues.nightly": { "type": "Object", "desc": "The config for nightly job queue" }, "queues.backendRuntime": { "type": "Object", "desc": "The config for backend runtime job queue" } }, "throttle": { "enabled": { "type": "Boolean", "desc": "Whether the throttler is enabled." }, "throttlers.default": { "type": "Object", "desc": "The config for the default throttler." }, "throttlers.strict": { "type": "Object", "desc": "The config for the strict throttler." } }, "auth": { "allowSignup": { "type": "Boolean", "desc": "Whether allow new registrations." }, "allowSignupForOauth": { "type": "Boolean", "desc": "Whether allow new registrations via configured oauth." }, "requireEmailDomainVerification": { "type": "Boolean", "desc": "Whether require email domain record verification before accessing restricted resources." }, "requireEmailVerification": { "type": "Boolean", "desc": "Whether require email verification before accessing restricted resources(not implemented)." }, "newAccountShareActionDelay": { "type": "Number", "desc": "Minimum account age in seconds before new accounts can invite members or create share links." }, "passwordRequirements": { "type": "Object", "desc": "The password strength requirements when set new password." }, "session.ttl": { "type": "Number", "desc": "Application auth expiration time in seconds." }, "session.ttr": { "type": "Number", "desc": "Application auth time to refresh in seconds." } }, "mailer": { "SMTP.name": { "type": "String", "desc": "Hostname used for SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.", "env": "MAILER_SERVERNAME" }, "SMTP.host": { "type": "String", "desc": "Host of the email server (e.g. smtp.gmail.com)", "env": "MAILER_HOST" }, "SMTP.port": { "type": "Number", "desc": "Port of the email server (they commonly are 25, 465 or 587)", "env": "MAILER_PORT" }, "SMTP.username": { "type": "String", "desc": "Username used to authenticate the email server", "env": "MAILER_USER" }, "SMTP.password": { "type": "String", "desc": "Password used to authenticate the email server", "env": "MAILER_PASSWORD" }, "SMTP.sender": { "type": "String", "desc": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")", "env": "MAILER_SENDER" }, "SMTP.ignoreTLS": { "type": "Boolean", "desc": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.", "env": "MAILER_IGNORE_TLS" }, "fallbackDomains": { "type": "Array", "desc": "The emails from these domains are always sent using the fallback SMTP server." }, "fallbackSMTP.name": { "type": "String", "desc": "Hostname used for fallback SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname." }, "fallbackSMTP.host": { "type": "String", "desc": "Host of the email server (e.g. smtp.gmail.com)" }, "fallbackSMTP.port": { "type": "Number", "desc": "Port of the email server (they commonly are 25, 465 or 587)" }, "fallbackSMTP.username": { "type": "String", "desc": "Username used to authenticate the email server" }, "fallbackSMTP.password": { "type": "String", "desc": "Password used to authenticate the email server" }, "fallbackSMTP.sender": { "type": "String", "desc": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")" }, "fallbackSMTP.ignoreTLS": { "type": "Boolean", "desc": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates." } }, "doc": { "experimental.yocto": { "type": "Boolean", "desc": "Use `y-octo` to merge updates at the same time when merging using Yjs." }, "history.interval": { "type": "Number", "desc": "The minimum time interval in milliseconds of creating a new history snapshot when doc get updated." } }, "permission": { "readModel": { "type": "String", "desc": "Permission data source for Rust evaluation", "env": "AFFINE_PERMISSION_READ_MODEL" }, "fallbackLegacyLoader": { "type": "Boolean", "desc": "Fallback from projection loader to legacy loader when projection input loading fails", "env": "AFFINE_PERMISSION_FALLBACK_LEGACY_LOADER" } }, "storages": { "avatar.publicPath": { "type": "String", "desc": "The public accessible path prefix for user avatars." }, "avatar.storage": { "type": "Object", "desc": "The config of storage for user avatars." }, "blob.storage": { "type": "Object", "desc": "The config of storage for all uploaded blobs(images, videos, etc.)." } }, "websocket": { "transports": { "type": "Array", "desc": "The enabled transports for accepting websocket traffics.", "link": "https://docs.nestjs.com/websockets/gateways#transports" }, "maxHttpBufferSize": { "type": "Number", "desc": "How many bytes or characters a message can be, before closing the session (to avoid DoS)." } }, "server": { "name": { "type": "String", "desc": "A recognizable name for the server. Will be shown when connected with AFFiNE Desktop." }, "externalUrl": { "type": "String", "desc": "Base url of AFFiNE server, used for generating external urls.\nDefault to be `[server.protocol]://[server.host][:server.port]` if not specified.\n ", "env": "AFFINE_SERVER_EXTERNAL_URL" }, "https": { "type": "Boolean", "desc": "Whether the server is hosted on a ssl enabled domain (https://).", "env": "AFFINE_SERVER_HTTPS" }, "host": { "type": "String", "desc": "Where the server get deployed(FQDN).", "env": "AFFINE_SERVER_HOST" }, "hosts": { "type": "Array", "desc": "Multiple hosts the server will accept requests from." }, "listenAddr": { "type": "String", "desc": "The address to listen on (e.g., 0.0.0.0 for IPv4, :: for IPv6).", "env": "LISTEN_ADDR" }, "port": { "type": "Number", "desc": "Which port the server will listen on.", "env": "AFFINE_SERVER_PORT" }, "path": { "type": "String", "desc": "Subpath where the server get deployed if there is one.(e.g. /affine)", "env": "AFFINE_SERVER_SUB_PATH" } }, "flags": { "allowGuestDemoWorkspace": { "type": "Boolean", "desc": "Whether allow guest users to create demo workspaces." } }, "docService": { "endpoint": { "type": "String", "desc": "The endpoint of the doc service.", "env": "DOC_SERVICE_ENDPOINT" } }, "telemetry": { "allowedOrigin": { "type": "Array", "desc": "Allowed origins for telemetry collection." }, "ga4.measurementId": { "type": "String", "desc": "GA4 Measurement ID for Measurement Protocol.", "env": "GA4_MEASUREMENT_ID" }, "ga4.apiSecret": { "type": "String", "desc": "GA4 API secret for Measurement Protocol.", "env": "GA4_API_SECRET" }, "dedupe.ttlHours": { "type": "Number", "desc": "Telemetry dedupe TTL in hours." }, "dedupe.maxEntries": { "type": "Number", "desc": "Telemetry dedupe max entries." }, "batch.maxEvents": { "type": "Number", "desc": "Max events per telemetry batch." } }, "client": { "versionControl.enabled": { "type": "Boolean", "desc": "Whether check version of client before accessing the server." }, "versionControl.requiredVersion": { "type": "String", "desc": "Allowed version range of the app that allowed to access the server. Requires 'client/versionControl.enabled' to be true to take effect." } }, "calendar": { "google": { "type": "Object", "desc": "Google Calendar integration config", "link": "https://developers.google.com/calendar/api/guides/push" }, "caldav": { "type": "Object", "desc": "CalDAV integration config" } }, "captcha": { "enabled": { "type": "Boolean", "desc": "Check captcha challenge when user authenticating the app." }, "config": { "type": "Object", "desc": "The config for the captcha plugin." } }, "copilot": { "enabled": { "type": "Boolean", "desc": "Whether to enable the copilot plugin.
Document: https://docs.affine.pro/self-host-affine/administer/ai" }, "byok.enabled": { "type": "Boolean", "desc": "Whether to enable workspace BYOK." }, "byok.allowedProviders": { "type": "Array", "desc": "The allowlist for workspace BYOK providers." }, "byok.allowCustomEndpoint": { "type": "Boolean", "desc": "Whether workspace BYOK custom endpoints are accepted." }, "providers.profiles": { "type": "Array", "desc": "The profile list for copilot providers." }, "providers.defaults": { "type": "Object", "desc": "The default provider ids for model output types and global fallback." }, "providers.openai": { "type": "Object", "desc": "The config for the openai provider.", "link": "https://github.com/openai/openai-node" }, "providers.cloudflareWorkersAi": { "type": "Object", "desc": "The config for the Cloudflare Workers AI provider." }, "providers.fal": { "type": "Object", "desc": "The config for the fal provider." }, "providers.gemini": { "type": "Object", "desc": "The config for the gemini provider." }, "providers.geminiVertex": { "type": "Object", "desc": "The config for the gemini provider in Google Vertex AI." }, "providers.anthropic": { "type": "Object", "desc": "The config for the anthropic provider." }, "providers.anthropicVertex": { "type": "Object", "desc": "The config for the anthropic provider in Google Vertex AI." }, "unsplash": { "type": "Object", "desc": "The config for the unsplash key." }, "exa": { "type": "Object", "desc": "The config for the exa web search key." }, "storage": { "type": "Object", "desc": "The config for the storage provider." } }, "indexer": { "enabled": { "type": "Boolean", "desc": "Enable indexer plugin", "env": "AFFINE_INDEXER_ENABLED" }, "provider.type": { "type": "String", "desc": "Indexer search service provider name", "env": "AFFINE_INDEXER_SEARCH_PROVIDER" }, "provider.endpoint": { "type": "String", "desc": "Indexer search service endpoint", "env": "AFFINE_INDEXER_SEARCH_ENDPOINT" }, "provider.apiKey": { "type": "String", "desc": "Indexer search service api key. Optional for elasticsearch", "link": "https://www.elastic.co/guide/server/current/api-key.html", "env": "AFFINE_INDEXER_SEARCH_API_KEY" }, "provider.username": { "type": "String", "desc": "Indexer search service auth username, if not set, basic auth will be disabled. Optional for elasticsearch", "link": "https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html", "env": "AFFINE_INDEXER_SEARCH_USERNAME" }, "provider.password": { "type": "String", "desc": "Indexer search service auth password, if not set, basic auth will be disabled. Optional for elasticsearch", "env": "AFFINE_INDEXER_SEARCH_PASSWORD" }, "autoIndex.batchSize": { "type": "Number", "desc": "Number of workspaces automatically indexed per batch" } }, "oauth": { "providers.google": { "type": "Object", "desc": "Google OAuth provider config", "link": "https://developers.google.com/identity/protocols/oauth2/web-server" }, "providers.github": { "type": "Object", "desc": "GitHub OAuth provider config", "link": "https://docs.github.com/en/apps/oauth-apps" }, "providers.oidc": { "type": "Object", "desc": "OIDC OAuth provider config", "link": "https://openid.net/specs/openid-connect-core-1_0.html" }, "providers.apple": { "type": "Object", "desc": "Apple OAuth provider config", "link": "https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/implementing_sign_in_with_apple_in_your_app" } }, "payment": { "enabled": { "type": "Boolean", "desc": "Whether enable payment plugin" }, "showLifetimePrice": { "type": "Boolean", "desc": "Whether enable lifetime price and allow user to pay for it." }, "stripe": { "type": "Object", "desc": "Stripe sdk options and credentials", "link": "https://docs.stripe.com/api" }, "revenuecat": { "type": "Object", "desc": "RevenueCat integration configs", "link": "https://www.revenuecat.com/docs/" } }, "worker": { "allowedOrigin": { "type": "Array", "desc": "Allowed origin" } } }