2126 lines
51 KiB
JSON
2126 lines
51 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"title": "Fluxer Config",
|
|
"type": "object",
|
|
"required": [
|
|
"env",
|
|
"domain",
|
|
"database",
|
|
"services",
|
|
"auth"
|
|
],
|
|
"if": {
|
|
"required": [
|
|
"instance"
|
|
],
|
|
"properties": {
|
|
"instance": {
|
|
"required": [
|
|
"deployment_mode"
|
|
],
|
|
"properties": {
|
|
"deployment_mode": {
|
|
"const": "microservices"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"required": [
|
|
"internal"
|
|
],
|
|
"properties": {
|
|
"services": {
|
|
"required": [
|
|
"app_proxy"
|
|
],
|
|
"properties": {
|
|
"s3": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"queue": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"media_proxy": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"admin": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"marketing": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"api": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"app_proxy": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"gateway": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
},
|
|
"server": {
|
|
"required": [
|
|
"port"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"properties": {
|
|
"$schema": {
|
|
"type": "string",
|
|
"description": "Optional reference to this JSON Schema for tooling support."
|
|
},
|
|
"env": {
|
|
"type": "string",
|
|
"description": "Runtime environment for the application. Controls behavior such as logging verbosity, error details, and optimization levels.",
|
|
"enum": [
|
|
"development",
|
|
"production",
|
|
"test"
|
|
]
|
|
},
|
|
"domain": {
|
|
"description": "Global domain and port configuration used to derive public endpoints for all services.",
|
|
"$ref": "#/$defs/domain"
|
|
},
|
|
"endpoint_overrides": {
|
|
"description": "Manual overrides for specific public endpoints. If set, these take precedence over automatically derived URLs.",
|
|
"$ref": "#/$defs/endpoint_overrides"
|
|
},
|
|
"internal": {
|
|
"description": "Internal network endpoints for service-to-service communication. Only required for microservices mode.",
|
|
"$ref": "#/$defs/internal",
|
|
"default": {}
|
|
},
|
|
"database": {
|
|
"description": "Primary database configuration. Selects the backend (Cassandra vs SQLite) and provides connection details.",
|
|
"$ref": "#/$defs/database"
|
|
},
|
|
"s3": {
|
|
"description": "S3-compatible object storage configuration.",
|
|
"$ref": "#/$defs/s3"
|
|
},
|
|
"services": {
|
|
"description": "Configuration for individual Fluxer services.",
|
|
"$ref": "#/$defs/services"
|
|
},
|
|
"auth": {
|
|
"description": "Authentication and security settings.",
|
|
"$ref": "#/$defs/auth"
|
|
},
|
|
"cookie": {
|
|
"description": "HTTP cookie settings.",
|
|
"$ref": "#/$defs/cookie",
|
|
"default": {}
|
|
},
|
|
"integrations": {
|
|
"description": "Third-party service integrations.",
|
|
"$ref": "#/$defs/integrations",
|
|
"default": {}
|
|
},
|
|
"instance": {
|
|
"description": "Instance-specific settings and policies.",
|
|
"$ref": "#/$defs/instance",
|
|
"default": {}
|
|
},
|
|
"csam": {
|
|
"description": "CSAM (Child Sexual Abuse Material) detection and reporting policies.",
|
|
"$ref": "#/$defs/csam",
|
|
"default": {}
|
|
},
|
|
"dev": {
|
|
"description": "Development-only overrides and flags. These should generally be disabled in production.",
|
|
"$ref": "#/$defs/dev",
|
|
"default": {}
|
|
},
|
|
"geoip": {
|
|
"description": "GeoIP database configuration.",
|
|
"$ref": "#/$defs/geoip",
|
|
"default": {}
|
|
},
|
|
"proxy": {
|
|
"description": "Reverse proxy and IP resolution settings.",
|
|
"$ref": "#/$defs/proxy",
|
|
"default": {}
|
|
},
|
|
"discovery": {
|
|
"description": "Guild discovery listing configuration.",
|
|
"$ref": "#/$defs/discovery",
|
|
"default": {}
|
|
},
|
|
"attachment_decay_enabled": {
|
|
"type": "boolean",
|
|
"description": "Whether to automatically delete old attachments.",
|
|
"default": true
|
|
},
|
|
"deletion_grace_period_hours": {
|
|
"type": "number",
|
|
"description": "Grace period in hours before soft-deleted items are permanently removed.",
|
|
"default": 72
|
|
},
|
|
"inactivity_deletion_threshold_days": {
|
|
"type": "number",
|
|
"description": "Days of inactivity after which data may be subject to deletion.",
|
|
"default": 365
|
|
},
|
|
"alerts": {
|
|
"description": "System alerting configuration.",
|
|
"$ref": "#/$defs/alerts"
|
|
},
|
|
"telemetry": {
|
|
"description": "OpenTelemetry configuration.",
|
|
"$ref": "#/$defs/telemetry",
|
|
"default": {}
|
|
},
|
|
"sentry": {
|
|
"description": "Sentry error reporting configuration.",
|
|
"$ref": "#/$defs/sentry",
|
|
"default": {}
|
|
},
|
|
"app_public": {
|
|
"description": "Public client-side configuration exposed to the frontend.",
|
|
"$ref": "#/$defs/app_public",
|
|
"default": {}
|
|
},
|
|
"federation": {
|
|
"description": "Federation configuration for connecting with other Fluxer instances.",
|
|
"$ref": "#/$defs/federation",
|
|
"default": {}
|
|
}
|
|
},
|
|
"$defs": {
|
|
"passkeys": {
|
|
"type": "object",
|
|
"description": "WebAuthn/Passkeys relying party settings.",
|
|
"properties": {
|
|
"rp_name": {
|
|
"type": "string",
|
|
"description": "Relying Party name displayed to users.",
|
|
"default": "Fluxer"
|
|
},
|
|
"rp_id": {
|
|
"type": "string",
|
|
"description": "Relying Party ID (domain) for WebAuthn credentials.",
|
|
"default": "fluxer.app"
|
|
},
|
|
"additional_allowed_origins": {
|
|
"type": "array",
|
|
"description": "List of allowed origins for WebAuthn registration/authentication.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"default": [
|
|
"https://web.fluxer.app",
|
|
"https://web.canary.fluxer.app"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"bluesky_key": {
|
|
"type": "object",
|
|
"required": [
|
|
"kid"
|
|
],
|
|
"properties": {
|
|
"kid": {
|
|
"type": "string",
|
|
"description": "JSON Web Key ID used when signing private key JWTs."
|
|
},
|
|
"private_key": {
|
|
"type": "string",
|
|
"description": "PEM-encoded private key used to authenticate to the Bluesky token endpoint."
|
|
},
|
|
"private_key_path": {
|
|
"type": "string",
|
|
"description": "Absolute filesystem path to a PEM private key file. Must be an absolute path because services may run from different working directories. Use this instead of private_key to avoid embedding the key in the config."
|
|
}
|
|
},
|
|
"anyOf": [
|
|
{
|
|
"required": [
|
|
"private_key"
|
|
]
|
|
},
|
|
{
|
|
"required": [
|
|
"private_key_path"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"bluesky": {
|
|
"type": "object",
|
|
"description": "Bluesky OAuth client configuration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Whether Bluesky OAuth connections are enabled.",
|
|
"default": true
|
|
},
|
|
"client_name": {
|
|
"type": "string",
|
|
"description": "Human-readable client name exposed to Bluesky.",
|
|
"default": "Fluxer"
|
|
},
|
|
"client_uri": {
|
|
"type": "string",
|
|
"description": "URI describing the client application.",
|
|
"default": ""
|
|
},
|
|
"logo_uri": {
|
|
"type": "string",
|
|
"description": "Optional logo presented during authorization.",
|
|
"default": "https://fluxerstatic.com/web/apple-touch-icon.png"
|
|
},
|
|
"tos_uri": {
|
|
"type": "string",
|
|
"description": "Terms of service URI exposed to Bluesky.",
|
|
"default": "https://fluxer.app/terms"
|
|
},
|
|
"policy_uri": {
|
|
"type": "string",
|
|
"description": "Privacy policy URI exposed to Bluesky.",
|
|
"default": "https://fluxer.app/privacy"
|
|
},
|
|
"keys": {
|
|
"type": "array",
|
|
"description": "Key definitions used to sign private key JWT assertions.",
|
|
"items": {
|
|
"$ref": "#/$defs/bluesky_key"
|
|
},
|
|
"default": []
|
|
}
|
|
},
|
|
"default": {
|
|
"enabled": true,
|
|
"client_name": "Fluxer",
|
|
"client_uri": "",
|
|
"logo_uri": "https://fluxerstatic.com/web/apple-touch-icon.png",
|
|
"tos_uri": "https://fluxer.app/terms",
|
|
"policy_uri": "https://fluxer.app/privacy",
|
|
"keys": []
|
|
}
|
|
},
|
|
"vapid": {
|
|
"type": "object",
|
|
"description": "VAPID keys for Web Push notifications.",
|
|
"required": [
|
|
"public_key",
|
|
"private_key"
|
|
],
|
|
"properties": {
|
|
"public_key": {
|
|
"type": "string",
|
|
"description": "VAPID Public Key."
|
|
},
|
|
"private_key": {
|
|
"type": "string",
|
|
"description": "VAPID Private Key."
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"description": "Contact email included in push service requests.",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"auth": {
|
|
"type": "object",
|
|
"description": "Global authentication configuration.",
|
|
"required": [
|
|
"vapid",
|
|
"sudo_mode_secret",
|
|
"connection_initiation_secret"
|
|
],
|
|
"properties": {
|
|
"sudo_mode_secret": {
|
|
"type": "string",
|
|
"description": "Secret key for verifying sudo mode tokens."
|
|
},
|
|
"connection_initiation_secret": {
|
|
"type": "string",
|
|
"description": "Secret key for signing connection initiation tokens."
|
|
},
|
|
"passkeys": {
|
|
"description": "Passkey configuration.",
|
|
"$ref": "#/$defs/passkeys",
|
|
"default": {}
|
|
},
|
|
"vapid": {
|
|
"description": "Web Push VAPID configuration.",
|
|
"$ref": "#/$defs/vapid"
|
|
},
|
|
"bluesky": {
|
|
"description": "Bluesky OAuth client configuration.",
|
|
"$ref": "#/$defs/bluesky",
|
|
"default": {
|
|
"enabled": true,
|
|
"client_name": "Fluxer",
|
|
"client_uri": "",
|
|
"logo_uri": "https://fluxerstatic.com/web/apple-touch-icon.png",
|
|
"tos_uri": "https://fluxer.app/terms",
|
|
"policy_uri": "https://fluxer.app/privacy",
|
|
"keys": []
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"cookie": {
|
|
"type": "object",
|
|
"description": "Session cookie configuration.",
|
|
"properties": {
|
|
"domain": {
|
|
"type": "string",
|
|
"description": "Domain attribute for cookies. Leave empty for host-only.",
|
|
"default": ""
|
|
},
|
|
"secure": {
|
|
"type": "boolean",
|
|
"description": "If true, sets the Secure flag on cookies.",
|
|
"default": false
|
|
}
|
|
}
|
|
},
|
|
"rate_limit": {
|
|
"type": "object",
|
|
"description": "Rate limiting parameters.",
|
|
"properties": {
|
|
"limit": {
|
|
"type": "number",
|
|
"description": "Maximum number of requests allowed within the window.",
|
|
"minimum": 1
|
|
},
|
|
"window_ms": {
|
|
"type": "number",
|
|
"description": "Time window in milliseconds.",
|
|
"minimum": 1
|
|
}
|
|
}
|
|
},
|
|
"cassandra": {
|
|
"type": "object",
|
|
"description": "Cassandra connection details.",
|
|
"required": [
|
|
"hosts",
|
|
"keyspace",
|
|
"local_dc",
|
|
"username",
|
|
"password"
|
|
],
|
|
"properties": {
|
|
"hosts": {
|
|
"type": "array",
|
|
"description": "Array of Cassandra contact points (hostnames or IPs).",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"keyspace": {
|
|
"type": "string",
|
|
"description": "Cassandra keyspace name."
|
|
},
|
|
"local_dc": {
|
|
"type": "string",
|
|
"description": "Local Data Center name for topology awareness."
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"description": "Cassandra authentication username."
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"description": "Cassandra authentication password."
|
|
}
|
|
}
|
|
},
|
|
"database": {
|
|
"type": "object",
|
|
"description": "Database backend selection and configuration.",
|
|
"required": [
|
|
"backend"
|
|
],
|
|
"properties": {
|
|
"backend": {
|
|
"type": "string",
|
|
"description": "Selected database backend. 'sqlite' is for dev/single-node, 'cassandra' for production.",
|
|
"enum": [
|
|
"cassandra",
|
|
"sqlite"
|
|
]
|
|
},
|
|
"cassandra": {
|
|
"description": "Configuration settings for Cassandra backend.",
|
|
"$ref": "#/$defs/cassandra"
|
|
},
|
|
"sqlite_path": {
|
|
"type": "string",
|
|
"description": "Filesystem path to the SQLite database file.",
|
|
"default": "./data/fluxer.db"
|
|
}
|
|
}
|
|
},
|
|
"s3_buckets": {
|
|
"type": "object",
|
|
"description": "Configuration of specific S3 bucket names.",
|
|
"properties": {
|
|
"cdn": {
|
|
"type": "string",
|
|
"description": "Bucket for CDN assets.",
|
|
"default": "fluxer"
|
|
},
|
|
"uploads": {
|
|
"type": "string",
|
|
"description": "Bucket for user uploads.",
|
|
"default": "fluxer-uploads"
|
|
},
|
|
"downloads": {
|
|
"type": "string",
|
|
"description": "Bucket for downloads.",
|
|
"default": "fluxer-downloads"
|
|
},
|
|
"reports": {
|
|
"type": "string",
|
|
"description": "Bucket for report data.",
|
|
"default": "fluxer-reports"
|
|
},
|
|
"harvests": {
|
|
"type": "string",
|
|
"description": "Bucket for data harvests.",
|
|
"default": "fluxer-harvests"
|
|
},
|
|
"static": {
|
|
"type": "string",
|
|
"description": "Bucket for static site assets.",
|
|
"default": "fluxer-static"
|
|
}
|
|
}
|
|
},
|
|
"s3": {
|
|
"type": "object",
|
|
"description": "S3 connection configuration.",
|
|
"required": [
|
|
"access_key_id",
|
|
"secret_access_key"
|
|
],
|
|
"properties": {
|
|
"endpoint": {
|
|
"type": "string",
|
|
"description": "S3 service endpoint URL.",
|
|
"default": "http://localhost:3900"
|
|
},
|
|
"presigned_url_base": {
|
|
"type": "string",
|
|
"description": "Base URL for presigned download URLs. If not set, defaults to the endpoint value. Set this to a public URL when the endpoint is internal."
|
|
},
|
|
"region": {
|
|
"type": "string",
|
|
"description": "S3 region.",
|
|
"default": "local"
|
|
},
|
|
"access_key_id": {
|
|
"type": "string",
|
|
"description": "S3 Access Key ID."
|
|
},
|
|
"secret_access_key": {
|
|
"type": "string",
|
|
"description": "S3 Secret Access Key."
|
|
},
|
|
"buckets": {
|
|
"description": "Mapping of logical buckets to actual S3 bucket names.",
|
|
"$ref": "#/$defs/s3_buckets",
|
|
"default": {}
|
|
}
|
|
}
|
|
},
|
|
"discovery": {
|
|
"type": "object",
|
|
"description": "Guild discovery listing configuration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Whether guild discovery is enabled on this instance.",
|
|
"default": true
|
|
},
|
|
"min_member_count": {
|
|
"type": "number",
|
|
"description": "Minimum number of members a guild needs before it can apply for discovery listing.",
|
|
"default": 1
|
|
}
|
|
}
|
|
},
|
|
"domain": {
|
|
"type": "object",
|
|
"description": "Configuration for domains and ports used to construct public URLs.",
|
|
"required": [
|
|
"base_domain"
|
|
],
|
|
"properties": {
|
|
"base_domain": {
|
|
"type": "string",
|
|
"description": "The primary domain name (e.g., example.com, localhost)."
|
|
},
|
|
"public_scheme": {
|
|
"type": "string",
|
|
"description": "The URL scheme for public endpoints.",
|
|
"enum": [
|
|
"http",
|
|
"https"
|
|
],
|
|
"default": "http"
|
|
},
|
|
"internal_scheme": {
|
|
"type": "string",
|
|
"description": "The URL scheme for internal endpoints.",
|
|
"enum": [
|
|
"http",
|
|
"https"
|
|
],
|
|
"default": "http"
|
|
},
|
|
"public_port": {
|
|
"type": "number",
|
|
"description": "The public-facing port number.",
|
|
"default": 8088
|
|
},
|
|
"internal_port": {
|
|
"type": "number",
|
|
"description": "The internal port number.",
|
|
"default": 8088
|
|
},
|
|
"static_cdn_domain": {
|
|
"type": "string",
|
|
"description": "Separate domain for static CDN assets (optional).",
|
|
"default": "fluxerstatic.com"
|
|
},
|
|
"invite_domain": {
|
|
"type": "string",
|
|
"description": "Domain for short invite links (optional).",
|
|
"default": ""
|
|
},
|
|
"gift_domain": {
|
|
"type": "string",
|
|
"description": "Domain for gift links (optional).",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"endpoint_overrides": {
|
|
"type": "object",
|
|
"description": "Explicit overrides for service endpoints. Use these if derived URLs are incorrect.",
|
|
"properties": {
|
|
"api": {
|
|
"type": "string",
|
|
"description": "Full URL override for the API endpoint."
|
|
},
|
|
"api_client": {
|
|
"type": "string",
|
|
"description": "Full URL override for the client-facing API endpoint."
|
|
},
|
|
"app": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Web App endpoint."
|
|
},
|
|
"gateway": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Gateway (WebSocket) endpoint."
|
|
},
|
|
"media": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Media endpoint."
|
|
},
|
|
"static_cdn": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Static CDN endpoint."
|
|
},
|
|
"admin": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Admin Panel endpoint."
|
|
},
|
|
"marketing": {
|
|
"type": "string",
|
|
"description": "Full URL override for the Marketing Site endpoint."
|
|
},
|
|
"invite": {
|
|
"type": "string",
|
|
"description": "Full URL override for Invite links."
|
|
},
|
|
"gift": {
|
|
"type": "string",
|
|
"description": "Full URL override for Gift links."
|
|
}
|
|
}
|
|
},
|
|
"internal": {
|
|
"type": "object",
|
|
"description": "Direct internal endpoints for backend services. In monolith mode these are served via paths on the main server.",
|
|
"properties": {
|
|
"kv": {
|
|
"type": "string",
|
|
"description": "Internal Valkey/Redis URL for key-value operations.",
|
|
"default": "redis://localhost:6379/0"
|
|
},
|
|
"kv_mode": {
|
|
"type": "string",
|
|
"description": "Valkey/Redis connection mode. Use 'standalone' for a single node or 'cluster' for a Valkey/Redis cluster.",
|
|
"enum": [
|
|
"standalone",
|
|
"cluster"
|
|
],
|
|
"default": "standalone"
|
|
},
|
|
"kv_cluster_nodes": {
|
|
"type": "array",
|
|
"description": "List of cluster node URLs when kv_mode is 'cluster'. Each entry should be a host:port string.",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"host": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"host",
|
|
"port"
|
|
]
|
|
},
|
|
"default": []
|
|
},
|
|
"kv_cluster_nat_map": {
|
|
"type": "object",
|
|
"description": "NAT mapping for Valkey/Redis cluster nodes. Maps internal addresses to external addresses for NAT traversal.",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"host": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"host",
|
|
"port"
|
|
]
|
|
},
|
|
"default": {}
|
|
},
|
|
"queue": {
|
|
"type": "string",
|
|
"description": "Internal URL for the Queue service.",
|
|
"default": "http://localhost:8088/queue"
|
|
},
|
|
"media_proxy": {
|
|
"type": "string",
|
|
"description": "Internal URL for the Media Proxy service.",
|
|
"default": "http://localhost:8088/media"
|
|
}
|
|
}
|
|
},
|
|
"instance": {
|
|
"type": "object",
|
|
"description": "Specific settings for this Fluxer instance.",
|
|
"properties": {
|
|
"deployment_mode": {
|
|
"type": "string",
|
|
"description": "Deployment mode. 'monolith' runs all services in one process (fluxer_server). 'microservices' requires separate processes/ports.",
|
|
"enum": [
|
|
"monolith",
|
|
"microservices"
|
|
],
|
|
"default": "monolith"
|
|
},
|
|
"self_hosted": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Indicates if this is a self-hosted instance."
|
|
},
|
|
"auto_join_invite_code": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Invite code to auto-join users to a guild upon registration."
|
|
},
|
|
"visionaries_guild_id": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Guild ID for Visionary members."
|
|
},
|
|
"operators_guild_id": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Guild ID for Operators."
|
|
},
|
|
"private_key_path": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Path to the x25519 private key for E2E encryption (generated on first startup if missing)."
|
|
}
|
|
}
|
|
},
|
|
"federation": {
|
|
"type": "object",
|
|
"description": "Federation configuration for connecting with other Fluxer instances.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable federation with other Fluxer instances."
|
|
}
|
|
}
|
|
},
|
|
"csam": {
|
|
"type": "object",
|
|
"description": "CSAM compliance configuration.",
|
|
"properties": {
|
|
"evidence_retention_days": {
|
|
"type": "number",
|
|
"default": 730,
|
|
"description": "Days to retain evidence."
|
|
},
|
|
"job_retention_days": {
|
|
"type": "number",
|
|
"default": 365,
|
|
"description": "Days to retain reporting jobs."
|
|
},
|
|
"cleanup_batch_size": {
|
|
"type": "number",
|
|
"default": 100,
|
|
"description": "Batch size for cleanup operations."
|
|
},
|
|
"queue": {
|
|
"type": "object",
|
|
"description": "CSAM scan queue configuration.",
|
|
"properties": {
|
|
"timeout_ms": {
|
|
"type": "number",
|
|
"default": 30000,
|
|
"description": "Maximum time to wait for a scan result (ms)."
|
|
},
|
|
"max_entries_per_batch": {
|
|
"type": "number",
|
|
"default": 5,
|
|
"description": "Maximum queue entries to process per consumer run."
|
|
},
|
|
"consumer_lock_ttl_seconds": {
|
|
"type": "number",
|
|
"default": 5,
|
|
"description": "TTL for consumer lock (seconds)."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"dev": {
|
|
"type": "object",
|
|
"description": "Development environment flags.",
|
|
"properties": {
|
|
"relax_registration_rate_limits": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Relax rate limits for registration."
|
|
},
|
|
"disable_rate_limits": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Disable all rate limits."
|
|
},
|
|
"test_mode_enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable test mode behaviors."
|
|
},
|
|
"test_harness_token": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Token for the test harness."
|
|
}
|
|
}
|
|
},
|
|
"geoip": {
|
|
"type": "object",
|
|
"description": "GeoIP database settings.",
|
|
"properties": {
|
|
"maxmind_db_path": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Path to MaxMind GeoIP database."
|
|
}
|
|
}
|
|
},
|
|
"proxy": {
|
|
"type": "object",
|
|
"description": "Proxy configuration.",
|
|
"properties": {
|
|
"trust_cf_connecting_ip": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Trust Cloudflare's CF-Connecting-IP header."
|
|
}
|
|
}
|
|
},
|
|
"captcha_provider": {
|
|
"type": "object",
|
|
"description": "Configuration for a specific CAPTCHA provider.",
|
|
"properties": {
|
|
"site_key": {
|
|
"type": "string",
|
|
"description": "Public site key.",
|
|
"default": ""
|
|
},
|
|
"secret_key": {
|
|
"type": "string",
|
|
"description": "Secret key for server-side verification.",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"captcha_integration": {
|
|
"type": "object",
|
|
"description": "CAPTCHA service integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable CAPTCHA verification.",
|
|
"default": false
|
|
},
|
|
"provider": {
|
|
"type": "string",
|
|
"description": "Selected CAPTCHA provider.",
|
|
"enum": [
|
|
"hcaptcha",
|
|
"turnstile",
|
|
"none"
|
|
],
|
|
"default": "none"
|
|
},
|
|
"hcaptcha": {
|
|
"description": "hCaptcha settings.",
|
|
"$ref": "#/$defs/captcha_provider",
|
|
"default": {}
|
|
},
|
|
"turnstile": {
|
|
"description": "Cloudflare Turnstile settings.",
|
|
"$ref": "#/$defs/captcha_provider",
|
|
"default": {}
|
|
}
|
|
}
|
|
},
|
|
"clamav_integration": {
|
|
"type": "object",
|
|
"description": "ClamAV antivirus integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable ClamAV scanning."
|
|
},
|
|
"host": {
|
|
"type": "string",
|
|
"default": "clamav",
|
|
"description": "ClamAV host."
|
|
},
|
|
"port": {
|
|
"type": "number",
|
|
"default": 3310,
|
|
"description": "ClamAV port."
|
|
},
|
|
"fail_open": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "If true, allow files if scanning fails."
|
|
}
|
|
}
|
|
},
|
|
"cloudflare": {
|
|
"type": "object",
|
|
"description": "Cloudflare integration.",
|
|
"properties": {
|
|
"purge_enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable automatic cache purging."
|
|
},
|
|
"zone_id": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Cloudflare Zone ID."
|
|
},
|
|
"api_token": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Cloudflare API token for cache purge."
|
|
}
|
|
}
|
|
},
|
|
"csam_integration": {
|
|
"type": "object",
|
|
"description": "Unified CSAM scanning integration configuration supporting multiple providers.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable CSAM scanning."
|
|
},
|
|
"provider": {
|
|
"type": "string",
|
|
"enum": [
|
|
"photo_dna",
|
|
"arachnid_shield"
|
|
],
|
|
"default": "photo_dna",
|
|
"description": "The CSAM scanning provider to use."
|
|
},
|
|
"photo_dna": {
|
|
"type": "object",
|
|
"description": "PhotoDNA provider configuration.",
|
|
"properties": {
|
|
"hash_service_url": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "URL for the hash generation service."
|
|
},
|
|
"hash_service_timeout_ms": {
|
|
"type": "number",
|
|
"default": 15000,
|
|
"description": "Timeout for hash generation in milliseconds."
|
|
},
|
|
"match_endpoint": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "URL for the PhotoDNA match service."
|
|
},
|
|
"subscription_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Subscription key for the match service."
|
|
},
|
|
"match_enhance": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable enhanced matching."
|
|
},
|
|
"rate_limit_rps": {
|
|
"type": "number",
|
|
"default": 5,
|
|
"description": "Rate limit requests per second."
|
|
}
|
|
}
|
|
},
|
|
"arachnid_shield": {
|
|
"type": "object",
|
|
"description": "Arachnid Shield provider configuration.",
|
|
"properties": {
|
|
"endpoint": {
|
|
"type": "string",
|
|
"default": "https://shield.projectarachnid.com/v1/media",
|
|
"description": "Arachnid Shield API endpoint."
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Basic auth username."
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Basic auth password."
|
|
},
|
|
"timeout_ms": {
|
|
"type": "number",
|
|
"default": 30000,
|
|
"description": "Request timeout in milliseconds."
|
|
},
|
|
"max_retries": {
|
|
"type": "number",
|
|
"default": 3,
|
|
"description": "Maximum number of retry attempts."
|
|
},
|
|
"retry_backoff_ms": {
|
|
"type": "number",
|
|
"default": 1000,
|
|
"description": "Base backoff time for retries in milliseconds."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"smtp_email": {
|
|
"type": "object",
|
|
"description": "SMTP transport configuration for email delivery.",
|
|
"required": [
|
|
"host",
|
|
"port",
|
|
"username",
|
|
"password"
|
|
],
|
|
"properties": {
|
|
"host": {
|
|
"type": "string",
|
|
"description": "SMTP server hostname."
|
|
},
|
|
"port": {
|
|
"type": "number",
|
|
"description": "SMTP port number.",
|
|
"default": 587
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"description": "SMTP authentication username."
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"description": "SMTP authentication password."
|
|
},
|
|
"secure": {
|
|
"type": "boolean",
|
|
"description": "Use TLS when connecting to the SMTP server.",
|
|
"default": true
|
|
}
|
|
}
|
|
},
|
|
"email_integration": {
|
|
"type": "object",
|
|
"description": "Email delivery service integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable email sending.",
|
|
"default": false
|
|
},
|
|
"provider": {
|
|
"type": "string",
|
|
"description": "Email provider selection.",
|
|
"enum": [
|
|
"smtp",
|
|
"none"
|
|
],
|
|
"default": "none"
|
|
},
|
|
"webhook_secret": {
|
|
"type": "string",
|
|
"description": "Sweego webhook signing secret (base64-encoded)."
|
|
},
|
|
"from_email": {
|
|
"type": "string",
|
|
"description": "Default sender email address.",
|
|
"default": ""
|
|
},
|
|
"from_name": {
|
|
"type": "string",
|
|
"description": "Default sender name.",
|
|
"default": "Fluxer"
|
|
},
|
|
"smtp": {
|
|
"$ref": "#/$defs/smtp_email"
|
|
}
|
|
},
|
|
"if": {
|
|
"required": [
|
|
"enabled",
|
|
"provider"
|
|
],
|
|
"properties": {
|
|
"enabled": {
|
|
"const": true
|
|
},
|
|
"provider": {
|
|
"const": "smtp"
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"required": [
|
|
"smtp"
|
|
]
|
|
}
|
|
},
|
|
"gif": {
|
|
"type": "object",
|
|
"description": "GIF provider selection for the client-facing GIF picker.",
|
|
"properties": {
|
|
"provider": {
|
|
"type": "string",
|
|
"enum": [
|
|
"klipy",
|
|
"tenor"
|
|
],
|
|
"default": "klipy",
|
|
"description": "GIF provider to use for GIF search and sharing."
|
|
}
|
|
}
|
|
},
|
|
"integrations": {
|
|
"type": "object",
|
|
"description": "Collection of all external service integrations.",
|
|
"properties": {
|
|
"email": {
|
|
"$ref": "#/$defs/email_integration",
|
|
"default": {}
|
|
},
|
|
"sms": {
|
|
"$ref": "#/$defs/sms_integration",
|
|
"default": {}
|
|
},
|
|
"captcha": {
|
|
"$ref": "#/$defs/captcha_integration",
|
|
"default": {}
|
|
},
|
|
"voice": {
|
|
"$ref": "#/$defs/voice_integration",
|
|
"default": {}
|
|
},
|
|
"search": {
|
|
"$ref": "#/$defs/search_integration",
|
|
"default": {}
|
|
},
|
|
"stripe": {
|
|
"$ref": "#/$defs/stripe_integration",
|
|
"default": {}
|
|
},
|
|
"photo_dna": {
|
|
"$ref": "#/$defs/photo_dna_integration",
|
|
"default": {}
|
|
},
|
|
"ncmec": {
|
|
"$ref": "#/$defs/ncmec_integration",
|
|
"default": {}
|
|
},
|
|
"clamav": {
|
|
"$ref": "#/$defs/clamav_integration",
|
|
"default": {}
|
|
},
|
|
"gif": {
|
|
"$ref": "#/$defs/gif",
|
|
"default": {}
|
|
},
|
|
"klipy": {
|
|
"$ref": "#/$defs/klipy",
|
|
"default": {}
|
|
},
|
|
"tenor": {
|
|
"$ref": "#/$defs/tenor",
|
|
"default": {}
|
|
},
|
|
"youtube": {
|
|
"$ref": "#/$defs/youtube",
|
|
"default": {}
|
|
},
|
|
"cloudflare": {
|
|
"$ref": "#/$defs/cloudflare",
|
|
"default": {}
|
|
}
|
|
}
|
|
},
|
|
"klipy": {
|
|
"type": "object",
|
|
"description": "KLIPY GIF API integration.",
|
|
"properties": {
|
|
"api_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "KLIPY API Key."
|
|
}
|
|
}
|
|
},
|
|
"ncmec_integration": {
|
|
"type": "object",
|
|
"description": "NCMEC CyberTipline integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable NCMEC reporting."
|
|
},
|
|
"base_url": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Base URL for the CyberTipline Reporting API (e.g., https://report.cybertip.org/ispws)."
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Username for CyberTipline basic authentication."
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Password for CyberTipline basic authentication."
|
|
}
|
|
}
|
|
},
|
|
"photo_dna_integration": {
|
|
"type": "object",
|
|
"description": "PhotoDNA integration for hash matching.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable PhotoDNA."
|
|
},
|
|
"hash_service_url": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "URL for the hash generation service."
|
|
},
|
|
"hash_service_timeout_ms": {
|
|
"type": "number",
|
|
"default": 15000,
|
|
"description": "Timeout for hash generation."
|
|
},
|
|
"match_endpoint": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "URL for the match service."
|
|
},
|
|
"subscription_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Subscription key for the match service."
|
|
},
|
|
"match_enhance": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable enhanced matching."
|
|
},
|
|
"rate_limit_rps": {
|
|
"type": "number",
|
|
"default": 5,
|
|
"description": "Rate limit requests per second."
|
|
}
|
|
}
|
|
},
|
|
"search_integration": {
|
|
"type": "object",
|
|
"description": "Search engine integration. Supports Meilisearch and Elasticsearch backends.",
|
|
"properties": {
|
|
"engine": {
|
|
"type": "string",
|
|
"description": "Search engine backend to use.",
|
|
"enum": [
|
|
"meilisearch",
|
|
"elasticsearch"
|
|
],
|
|
"default": "meilisearch"
|
|
},
|
|
"url": {
|
|
"type": "string",
|
|
"description": "Search engine HTTP API URL. Used by both Meilisearch and Elasticsearch.",
|
|
"default": "http://127.0.0.1:7700"
|
|
},
|
|
"api_key": {
|
|
"type": "string",
|
|
"description": "API key for authenticating with the search engine. For Meilisearch, this is the master or admin key. For Elasticsearch, this is an API key.",
|
|
"default": ""
|
|
},
|
|
"username": {
|
|
"type": "string",
|
|
"description": "Username for Elasticsearch basic authentication. Only used when engine is elasticsearch and api_key is not set.",
|
|
"default": ""
|
|
},
|
|
"password": {
|
|
"type": "string",
|
|
"description": "Password for Elasticsearch basic authentication. Only used when engine is elasticsearch and api_key is not set.",
|
|
"default": ""
|
|
}
|
|
},
|
|
"required": [
|
|
"url",
|
|
"api_key"
|
|
]
|
|
},
|
|
"sms_integration": {
|
|
"type": "object",
|
|
"description": "SMS service integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable SMS sending.",
|
|
"default": false
|
|
},
|
|
"account_sid": {
|
|
"type": "string",
|
|
"description": "Twilio account SID."
|
|
},
|
|
"auth_token": {
|
|
"type": "string",
|
|
"description": "Twilio auth token."
|
|
},
|
|
"verify_service_sid": {
|
|
"type": "string",
|
|
"description": "Twilio Verify service SID."
|
|
}
|
|
},
|
|
"if": {
|
|
"required": [
|
|
"enabled"
|
|
],
|
|
"properties": {
|
|
"enabled": {
|
|
"const": true
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"required": [
|
|
"account_sid",
|
|
"auth_token",
|
|
"verify_service_sid"
|
|
]
|
|
}
|
|
},
|
|
"stripe_prices": {
|
|
"type": "object",
|
|
"description": "Stripe Price IDs for subscription products.",
|
|
"properties": {
|
|
"monthly_usd": {
|
|
"type": "string",
|
|
"description": "Monthly subscription USD price ID.",
|
|
"default": ""
|
|
},
|
|
"monthly_eur": {
|
|
"type": "string",
|
|
"description": "Monthly subscription EUR price ID.",
|
|
"default": ""
|
|
},
|
|
"yearly_usd": {
|
|
"type": "string",
|
|
"description": "Yearly subscription USD price ID.",
|
|
"default": ""
|
|
},
|
|
"yearly_eur": {
|
|
"type": "string",
|
|
"description": "Yearly subscription EUR price ID.",
|
|
"default": ""
|
|
},
|
|
"visionary_usd": {
|
|
"type": "string",
|
|
"description": "Visionary tier USD price ID.",
|
|
"default": ""
|
|
},
|
|
"visionary_eur": {
|
|
"type": "string",
|
|
"description": "Visionary tier EUR price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_visionary_usd": {
|
|
"type": "string",
|
|
"description": "Gift Visionary USD price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_visionary_eur": {
|
|
"type": "string",
|
|
"description": "Gift Visionary EUR price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_1_month_usd": {
|
|
"type": "string",
|
|
"description": "Gift 1 Month USD price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_1_month_eur": {
|
|
"type": "string",
|
|
"description": "Gift 1 Month EUR price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_1_year_usd": {
|
|
"type": "string",
|
|
"description": "Gift 1 Year USD price ID.",
|
|
"default": ""
|
|
},
|
|
"gift_1_year_eur": {
|
|
"type": "string",
|
|
"description": "Gift 1 Year EUR price ID.",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"stripe_integration": {
|
|
"type": "object",
|
|
"description": "Stripe payments integration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable Stripe payments.",
|
|
"default": false
|
|
},
|
|
"secret_key": {
|
|
"type": "string",
|
|
"description": "Stripe Secret Key."
|
|
},
|
|
"webhook_secret": {
|
|
"type": "string",
|
|
"description": "Stripe Webhook Signing Secret."
|
|
},
|
|
"prices": {
|
|
"description": "Stripe Price ID configuration.",
|
|
"$ref": "#/$defs/stripe_prices"
|
|
}
|
|
},
|
|
"if": {
|
|
"required": [
|
|
"enabled"
|
|
],
|
|
"properties": {
|
|
"enabled": {
|
|
"const": true
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"required": [
|
|
"secret_key",
|
|
"webhook_secret"
|
|
]
|
|
}
|
|
},
|
|
"tenor": {
|
|
"type": "object",
|
|
"description": "Tenor GIF API integration.",
|
|
"properties": {
|
|
"api_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Tenor API key."
|
|
}
|
|
}
|
|
},
|
|
"voice_integration": {
|
|
"type": "object",
|
|
"description": "Real-time voice/video integration (LiveKit).",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable voice/video features.",
|
|
"default": false
|
|
},
|
|
"api_key": {
|
|
"type": "string",
|
|
"description": "LiveKit API Key used for config-driven default_region bootstrap. Optional when voice topology is managed in the admin panel."
|
|
},
|
|
"api_secret": {
|
|
"type": "string",
|
|
"description": "LiveKit API Secret used for config-driven default_region bootstrap. Optional when voice topology is managed in the admin panel."
|
|
},
|
|
"webhook_url": {
|
|
"type": "string",
|
|
"description": "URL for LiveKit webhooks.",
|
|
"default": ""
|
|
},
|
|
"url": {
|
|
"type": "string",
|
|
"description": "LiveKit Server URL (client signal endpoint for WebSocket connections).",
|
|
"default": ""
|
|
},
|
|
"default_region": {
|
|
"type": "object",
|
|
"description": "Default voice region to create on startup if none exist. When provided, automatically creates this region and a server pointing to the configured LiveKit URL.",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Unique identifier for the region (e.g. 'default', 'eu-west')."
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"description": "Display name for the region."
|
|
},
|
|
"emoji": {
|
|
"type": "string",
|
|
"description": "Emoji icon for the region (e.g. '🌐', '🇪🇺')."
|
|
},
|
|
"latitude": {
|
|
"type": "number",
|
|
"description": "Latitude coordinate for the region."
|
|
},
|
|
"longitude": {
|
|
"type": "number",
|
|
"description": "Longitude coordinate for the region."
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name",
|
|
"emoji",
|
|
"latitude",
|
|
"longitude"
|
|
]
|
|
}
|
|
},
|
|
"if": {
|
|
"required": [
|
|
"enabled",
|
|
"default_region"
|
|
],
|
|
"properties": {
|
|
"enabled": {
|
|
"const": true
|
|
}
|
|
}
|
|
},
|
|
"then": {
|
|
"required": [
|
|
"api_key",
|
|
"api_secret"
|
|
]
|
|
}
|
|
},
|
|
"youtube": {
|
|
"type": "object",
|
|
"description": "YouTube API integration.",
|
|
"properties": {
|
|
"api_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "YouTube API Key."
|
|
}
|
|
}
|
|
},
|
|
"admin_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the Admin Panel service.",
|
|
"required": [
|
|
"secret_key_base",
|
|
"oauth_client_secret"
|
|
],
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 3001
|
|
},
|
|
"secret_key_base": {
|
|
"type": "string",
|
|
"description": "Base secret key for signing admin session tokens."
|
|
},
|
|
"base_path": {
|
|
"type": "string",
|
|
"description": "URL base path for the admin interface.",
|
|
"default": "/admin"
|
|
},
|
|
"oauth_client_secret": {
|
|
"type": "string",
|
|
"description": "OAuth Client Secret for admin authentication."
|
|
},
|
|
"rate_limit": {
|
|
"description": "Rate limiting configuration for the Admin service.",
|
|
"$ref": "#/$defs/rate_limit"
|
|
}
|
|
}
|
|
},
|
|
"api_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the main API service.",
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8080
|
|
},
|
|
"host": {
|
|
"type": "string",
|
|
"description": "Network interface to bind to.",
|
|
"default": "0.0.0.0"
|
|
},
|
|
"unfurl_ignored_hosts": {
|
|
"type": "array",
|
|
"description": "List of hostnames or IPs to ignore when unfurling URLs.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"default": [
|
|
"localhost",
|
|
"127.0.0.1"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"app_proxy_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the App Proxy service (frontend server).",
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8773
|
|
},
|
|
"static_cdn_endpoint": {
|
|
"type": "string",
|
|
"description": "URL endpoint for serving static assets via CDN.",
|
|
"default": ""
|
|
},
|
|
"assets_dir": {
|
|
"type": "string",
|
|
"description": "Filesystem directory containing static assets.",
|
|
"default": "./assets"
|
|
}
|
|
}
|
|
},
|
|
"gateway_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the Gateway service (WebSocket).",
|
|
"required": [
|
|
"admin_reload_secret",
|
|
"media_proxy_endpoint"
|
|
],
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8771
|
|
},
|
|
"admin_reload_secret": {
|
|
"type": "string",
|
|
"description": "Secret used to trigger code hot-swapping/reloads."
|
|
},
|
|
"identify_rate_limit_enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable rate limiting for Gateway IDENTIFY opcodes.",
|
|
"default": false
|
|
},
|
|
"push_enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable push notification delivery.",
|
|
"default": true
|
|
},
|
|
"push_user_guild_settings_cache_mb": {
|
|
"type": "number",
|
|
"description": "Memory cache size (MB) for user guild settings.",
|
|
"default": 1024
|
|
},
|
|
"push_subscriptions_cache_mb": {
|
|
"type": "number",
|
|
"description": "Memory cache size (MB) for push subscriptions.",
|
|
"default": 1024
|
|
},
|
|
"push_blocked_ids_cache_mb": {
|
|
"type": "number",
|
|
"description": "Memory cache size (MB) for blocked user IDs.",
|
|
"default": 1024
|
|
},
|
|
"push_badge_counts_cache_mb": {
|
|
"type": "number",
|
|
"description": "Memory cache size (MB) for badge counts.",
|
|
"default": 256
|
|
},
|
|
"push_badge_counts_cache_ttl_seconds": {
|
|
"type": "number",
|
|
"description": "TTL in seconds for badge counts cache.",
|
|
"default": 60
|
|
},
|
|
"media_proxy_endpoint": {
|
|
"type": "string",
|
|
"description": "Endpoint URL of the Media Proxy service."
|
|
},
|
|
"logger_level": {
|
|
"type": "string",
|
|
"description": "Logging level (e.g., debug, info, warn, error).",
|
|
"default": "info"
|
|
},
|
|
"release_node": {
|
|
"type": "string",
|
|
"description": "Erlang node name for the release.",
|
|
"default": "fluxer_gateway@gateway"
|
|
},
|
|
"gateway_metrics_enabled": {
|
|
"type": "boolean",
|
|
"description": "Enable collection of gateway metrics.",
|
|
"default": false
|
|
},
|
|
"gateway_metrics_report_interval_ms": {
|
|
"type": "number",
|
|
"description": "Interval in milliseconds to report gateway metrics.",
|
|
"default": 30000
|
|
},
|
|
"presence_cache_shards": {
|
|
"type": "number",
|
|
"description": "Number of shards for presence cache.",
|
|
"default": 1
|
|
},
|
|
"presence_bus_shards": {
|
|
"type": "number",
|
|
"description": "Number of shards for presence message bus.",
|
|
"default": 1
|
|
},
|
|
"presence_shards": {
|
|
"type": "number",
|
|
"description": "Number of shards for presence handling.",
|
|
"default": 1
|
|
},
|
|
"guild_shards": {
|
|
"type": "number",
|
|
"description": "Number of shards for guild handling.",
|
|
"default": 1
|
|
}
|
|
}
|
|
},
|
|
"marketing_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the Marketing site service.",
|
|
"required": [
|
|
"secret_key_base"
|
|
],
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"description": "Whether to enable the Marketing service within fluxer_server.",
|
|
"default": false
|
|
},
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8774
|
|
},
|
|
"host": {
|
|
"type": "string",
|
|
"description": "Network interface to bind to.",
|
|
"default": "0.0.0.0"
|
|
},
|
|
"secret_key_base": {
|
|
"type": "string",
|
|
"description": "Base secret key for marketing site sessions/tokens."
|
|
},
|
|
"base_path": {
|
|
"type": "string",
|
|
"description": "URL base path for the marketing site.",
|
|
"default": "/marketing"
|
|
}
|
|
}
|
|
},
|
|
"media_proxy_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the Media Proxy service.",
|
|
"required": [
|
|
"secret_key"
|
|
],
|
|
"properties": {
|
|
"host": {
|
|
"type": "string",
|
|
"description": "Network interface to bind to.",
|
|
"default": "0.0.0.0"
|
|
},
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8080
|
|
},
|
|
"secret_key": {
|
|
"type": "string",
|
|
"description": "Secret key used to sign and verify media URLs."
|
|
},
|
|
"require_cloudflare_edge": {
|
|
"type": "boolean",
|
|
"description": "If true, strictly requires requests to originate from Cloudflare edge IPs.",
|
|
"default": false
|
|
},
|
|
"static_mode": {
|
|
"type": "boolean",
|
|
"description": "If true, enables serving static files directly.",
|
|
"default": false
|
|
},
|
|
"rate_limit": {
|
|
"description": "Rate limiting configuration for the Media Proxy.",
|
|
"$ref": "#/$defs/rate_limit"
|
|
}
|
|
}
|
|
},
|
|
"nats_services": {
|
|
"type": "object",
|
|
"description": "Configuration for NATS messaging.",
|
|
"properties": {
|
|
"core_url": {
|
|
"type": "string",
|
|
"description": "NATS Core server URL for RPC.",
|
|
"default": "nats://127.0.0.1:4222"
|
|
},
|
|
"jetstream_url": {
|
|
"type": "string",
|
|
"description": "NATS JetStream server URL for job queues.",
|
|
"default": "nats://127.0.0.1:4223"
|
|
},
|
|
"auth_token": {
|
|
"type": "string",
|
|
"description": "Authentication token for NATS connections.",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"queue_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the Job Queue service.",
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8088
|
|
},
|
|
"concurrency": {
|
|
"type": "number",
|
|
"description": "Number of concurrent worker threads.",
|
|
"default": 1
|
|
},
|
|
"data_dir": {
|
|
"type": "string",
|
|
"description": "Filesystem path to store queue data.",
|
|
"default": "./data/queue"
|
|
},
|
|
"default_visibility_timeout_ms": {
|
|
"type": "number",
|
|
"description": "Default time in milliseconds a message remains invisible after being received.",
|
|
"default": 30000
|
|
},
|
|
"snapshot_every_ms": {
|
|
"type": "number",
|
|
"description": "Interval in milliseconds to take queue snapshots.",
|
|
"default": 60000
|
|
},
|
|
"snapshot_after_ops": {
|
|
"type": "number",
|
|
"description": "Number of operations after which to take a queue snapshot.",
|
|
"default": 10000
|
|
},
|
|
"snapshot_zstd_level": {
|
|
"type": "number",
|
|
"description": "Zstd compression level for snapshots (1-22).",
|
|
"default": 3
|
|
},
|
|
"secret": {
|
|
"type": "string",
|
|
"description": "Secret for queue API authentication.",
|
|
"default": ""
|
|
}
|
|
}
|
|
},
|
|
"s3_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the S3-compatible storage service.",
|
|
"properties": {
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 3900
|
|
},
|
|
"host": {
|
|
"type": "string",
|
|
"description": "Network interface to bind to.",
|
|
"default": "0.0.0.0"
|
|
},
|
|
"data_dir": {
|
|
"type": "string",
|
|
"description": "Filesystem path to store S3 data objects.",
|
|
"default": "./data/s3"
|
|
},
|
|
"export_timeout": {
|
|
"type": "number",
|
|
"description": "Timeout in milliseconds for data export operations.",
|
|
"default": 30000
|
|
},
|
|
"rate_limit": {
|
|
"description": "Rate limiting configuration for the S3 service.",
|
|
"$ref": "#/$defs/rate_limit"
|
|
}
|
|
}
|
|
},
|
|
"server_service": {
|
|
"type": "object",
|
|
"description": "Configuration for the main Fluxer Server.",
|
|
"properties": {
|
|
"host": {
|
|
"type": "string",
|
|
"description": "Network interface to bind to.",
|
|
"default": "0.0.0.0"
|
|
},
|
|
"port": {
|
|
"type": "number",
|
|
"description": "Port to listen on.",
|
|
"default": 8772
|
|
},
|
|
"static_dir": {
|
|
"type": "string",
|
|
"description": "Path to static assets directory for the web app. Required in production."
|
|
}
|
|
}
|
|
},
|
|
"services": {
|
|
"type": "object",
|
|
"description": "Container for all service-specific configurations.",
|
|
"required": [
|
|
"media_proxy",
|
|
"admin",
|
|
"gateway"
|
|
],
|
|
"properties": {
|
|
"s3": {
|
|
"$ref": "#/$defs/s3_service",
|
|
"default": {}
|
|
},
|
|
"nats": {
|
|
"$ref": "#/$defs/nats_services",
|
|
"default": {}
|
|
},
|
|
"queue": {
|
|
"$ref": "#/$defs/queue_service",
|
|
"default": {}
|
|
},
|
|
"media_proxy": {
|
|
"$ref": "#/$defs/media_proxy_service"
|
|
},
|
|
"admin": {
|
|
"$ref": "#/$defs/admin_service"
|
|
},
|
|
"marketing": {
|
|
"$ref": "#/$defs/marketing_service"
|
|
},
|
|
"api": {
|
|
"$ref": "#/$defs/api_service",
|
|
"default": {}
|
|
},
|
|
"app_proxy": {
|
|
"$ref": "#/$defs/app_proxy_service"
|
|
},
|
|
"gateway": {
|
|
"$ref": "#/$defs/gateway_service"
|
|
},
|
|
"server": {
|
|
"$ref": "#/$defs/server_service",
|
|
"default": {}
|
|
}
|
|
}
|
|
},
|
|
"alerts": {
|
|
"type": "object",
|
|
"description": "Alerting settings.",
|
|
"properties": {
|
|
"webhook_url": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Webhook URL for system alerts."
|
|
}
|
|
}
|
|
},
|
|
"telemetry": {
|
|
"type": "object",
|
|
"description": "OpenTelemetry observability settings.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable OpenTelemetry."
|
|
},
|
|
"otlp_endpoint": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "OTLP collector endpoint."
|
|
},
|
|
"api_key": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "API Key for telemetry service."
|
|
},
|
|
"service_name": {
|
|
"type": "string",
|
|
"default": "fluxer",
|
|
"description": "Service name reported to telemetry."
|
|
},
|
|
"environment": {
|
|
"type": "string",
|
|
"default": "development",
|
|
"description": "Environment name (dev, prod, etc)."
|
|
},
|
|
"trace_sampling_ratio": {
|
|
"type": "number",
|
|
"minimum": 0,
|
|
"maximum": 1,
|
|
"default": 1,
|
|
"description": "Sampling ratio for traces (0.0 to 1.0)."
|
|
},
|
|
"export_timeout": {
|
|
"type": "number",
|
|
"minimum": 1,
|
|
"default": 30000,
|
|
"description": "Timeout in milliseconds for exporting telemetry data."
|
|
},
|
|
"metric_export_interval_ms": {
|
|
"type": "number",
|
|
"minimum": 1,
|
|
"default": 60000,
|
|
"description": "Interval in milliseconds between metric exports."
|
|
},
|
|
"ignore_incoming_paths": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"default": [
|
|
"/_health"
|
|
],
|
|
"description": "HTTP paths to exclude from tracing."
|
|
}
|
|
}
|
|
},
|
|
"sentry": {
|
|
"type": "object",
|
|
"description": "Sentry configuration.",
|
|
"properties": {
|
|
"enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable Sentry reporting."
|
|
},
|
|
"dsn": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Sentry DSN."
|
|
}
|
|
}
|
|
},
|
|
"app_public": {
|
|
"type": "object",
|
|
"description": "Public configuration exposed to the frontend application.",
|
|
"properties": {
|
|
"api_version": {
|
|
"type": "number",
|
|
"default": 1,
|
|
"description": "API Version."
|
|
},
|
|
"bootstrap_api_endpoint": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Bootstrap API endpoint."
|
|
},
|
|
"bootstrap_api_public_endpoint": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Public Bootstrap API endpoint."
|
|
},
|
|
"sentry_dsn": {
|
|
"type": "string",
|
|
"default": "",
|
|
"description": "Frontend Sentry DSN."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|