name: fluxer x-fluxer-postgres-env: &fluxer-postgres-env FLUXER_DATABASE_BACKEND: postgres FLUXER_POSTGRES_HOST: ${FLUXER_POSTGRES_HOST:-postgres} FLUXER_POSTGRES_PORT: ${FLUXER_POSTGRES_PORT:-} FLUXER_POSTGRES_DATABASE: ${FLUXER_POSTGRES_DATABASE:-} FLUXER_POSTGRES_USERNAME: ${FLUXER_POSTGRES_USERNAME:-} FLUXER_POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env} FLUXER_POSTGRES_URL: ${FLUXER_POSTGRES_URL:-} FLUXER_POSTGRES_SSL: ${FLUXER_POSTGRES_SSL:-} FLUXER_POSTGRES_SSL_CA: ${FLUXER_POSTGRES_SSL_CA:-} FLUXER_POSTGRES_PREPARED_STATEMENTS: ${FLUXER_POSTGRES_PREPARED_STATEMENTS:-} FLUXER_POSTGRES_KV_TABLE: ${FLUXER_POSTGRES_KV_TABLE:-} x-fluxer-env: &fluxer-env <<: *fluxer-postgres-env FLUXER_ENV: production LOG_LEVEL: ${LOG_LEVEL:-} RUST_LOG: ${RUST_LOG:-} FLUXER_SELF_HOSTED: "true" FLUXER_BASE_DOMAIN: ${FLUXER_DOMAIN:?set FLUXER_DOMAIN in .env} FLUXER_PUBLIC_SCHEME: ${FLUXER_PUBLIC_SCHEME:-https} FLUXER_PUBLIC_PORT: ${FLUXER_PUBLIC_PORT:-443} FLUXER_PUBLIC_ORIGIN: ${FLUXER_PUBLIC_ORIGIN:-} FLUXER_TRUST_CLIENT_IP_HEADER: "${FLUXER_TRUST_CLIENT_IP_HEADER:-true}" FLUXER_CLIENT_IP_HEADER_NAME: ${FLUXER_CLIENT_IP_HEADER_NAME:-} FLUXER_API_HEADERS_TIMEOUT_MS: ${FLUXER_API_HEADERS_TIMEOUT_MS:-} FLUXER_API_REQUEST_TIMEOUT_MS: ${FLUXER_API_REQUEST_TIMEOUT_MS:-} FLUXER_API_MAX_INFLIGHT_REQUESTS: ${FLUXER_API_MAX_INFLIGHT_REQUESTS:-} FLUXER_API_IP_BAN_EXEMPT_IPS: ${FLUXER_API_IP_BAN_EXEMPT_IPS:-} FLUXER_IP_BAN_REFRESH_INTERVAL_MS: ${FLUXER_IP_BAN_REFRESH_INTERVAL_MS:-} FLUXER_APP_ORIGIN_ALIASES: ${FLUXER_APP_ORIGIN_ALIASES:-} FLUXER_BREACHED_PASSWORD_CHECK_ENABLED: ${FLUXER_BREACHED_PASSWORD_CHECK_ENABLED:-} FLUXER_BLOCKLIST_FEEDS_ENABLED: ${FLUXER_BLOCKLIST_FEEDS_ENABLED:-} FLUXER_GEOIP_DB_PATH: ${FLUXER_GEOIP_DB_PATH:-} FLUXER_API_ENDPOINT: ${FLUXER_API_ENDPOINT:-} FLUXER_API_CLIENT_ENDPOINT: ${FLUXER_API_CLIENT_ENDPOINT:-} FLUXER_APP_ENDPOINT: ${FLUXER_APP_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}} FLUXER_GATEWAY_ENDPOINT: ${FLUXER_GATEWAY_ENDPOINT:-} FLUXER_MEDIA_ENDPOINT: ${FLUXER_MEDIA_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}/media} FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT: ${FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT:-${FLUXER_MEDIA_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}/media}} FLUXER_STATIC_CDN_ENDPOINT: ${FLUXER_STATIC_CDN_ENDPOINT:-} FLUXER_ADMIN_ENDPOINT: ${FLUXER_ADMIN_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}${FLUXER_ADMIN_BASE_PATH:-/admin}} FLUXER_MARKETING_ENDPOINT: ${FLUXER_MARKETING_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}} FLUXER_INVITE_ENDPOINT: ${FLUXER_INVITE_ENDPOINT:-} FLUXER_GIFT_ENDPOINT: ${FLUXER_GIFT_ENDPOINT:-} FLUXER_STATIC_CDN_DOMAIN: ${FLUXER_STATIC_CDN_DOMAIN:-} FLUXER_INVITE_DOMAIN: ${FLUXER_INVITE_DOMAIN:-} FLUXER_GIFT_DOMAIN: ${FLUXER_GIFT_DOMAIN:-} FLUXER_KV_URL: ${FLUXER_KV_URL:-redis://valkey:6379/0} FLUXER_KV_MODE: ${FLUXER_KV_MODE:-} FLUXER_NATS_URL: ${FLUXER_NATS_URL:-nats://nats:4222} FLUXER_NATS_JETSTREAM_URL: ${FLUXER_NATS_JETSTREAM_URL:-${FLUXER_NATS_URL:-nats://nats:4222}} FLUXER_NATS_AUTH_TOKEN: ${FLUXER_NATS_AUTH_TOKEN:-} FLUXER_SVC_NATS_URL: ${FLUXER_SVC_NATS_URL:-${FLUXER_NATS_URL:-nats://nats:4222}} FLUXER_SVC_SHARD_COUNT: "1" FLUXER_SVC_MAX_CONCURRENT_REQUESTS: ${FLUXER_SVC_MAX_CONCURRENT_REQUESTS:-} FLUXER_SVC_CACHE_MAX_ENTRIES: ${FLUXER_SVC_CACHE_MAX_ENTRIES:-} FLUXER_SVC_CACHE_TTL_MS: ${FLUXER_SVC_CACHE_TTL_MS:-} FLUXER_GIF_SERVICE_NATS_CLIENT_NAME: ${FLUXER_GIF_SERVICE_NATS_CLIENT_NAME:-} FLUXER_GIF_SERVICE_TIMEOUT_MS: ${FLUXER_GIF_SERVICE_TIMEOUT_MS:-} FLUXER_GIF_SERVICE_REGISTER_SHARE_TIMEOUT_MS: ${FLUXER_GIF_SERVICE_REGISTER_SHARE_TIMEOUT_MS:-} FLUXER_USERS_SERVICE_NATS_CLIENT_NAME: ${FLUXER_USERS_SERVICE_NATS_CLIENT_NAME:-} FLUXER_USERS_SERVICE_TIMEOUT_MS: ${FLUXER_USERS_SERVICE_TIMEOUT_MS:-} FLUXER_USERS_SERVICE_INFLIGHT_MAX_ENTRIES: ${FLUXER_USERS_SERVICE_INFLIGHT_MAX_ENTRIES:-} FLUXER_SNOWFLAKE_SERVICE_NATS_CLIENT_NAME: ${FLUXER_SNOWFLAKE_SERVICE_NATS_CLIENT_NAME:-} FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE: ${FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE:-} FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK: ${FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK:-} FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS: ${FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS:-} FLUXER_SNOWFLAKE_SERVICE_REQUEST_TIMEOUT_MS: ${FLUXER_SNOWFLAKE_SERVICE_REQUEST_TIMEOUT_MS:-} FLUXER_SEARCH_ENGINE: ${FLUXER_SEARCH_ENGINE:-meilisearch} FLUXER_SEARCH_URL: ${FLUXER_SEARCH_URL:-http://meilisearch:7700} FLUXER_SEARCH_API_KEY: ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY in .env} FLUXER_SEARCH_USERNAME: ${FLUXER_SEARCH_USERNAME:-} FLUXER_SEARCH_PASSWORD: ${FLUXER_SEARCH_PASSWORD:-} FLUXER_SEARCH_TLS_REJECT_UNAUTHORIZED: ${FLUXER_SEARCH_TLS_REJECT_UNAUTHORIZED:-} FLUXER_S3_ENDPOINT: ${FLUXER_S3_ENDPOINT:-http://seaweedfs:8333} FLUXER_S3_PUBLIC_ENDPOINT: ${FLUXER_S3_PUBLIC_ENDPOINT:-${FLUXER_S3_ENDPOINT:-http://seaweedfs:8333}} FLUXER_S3_REGION: ${FLUXER_S3_REGION:-us-east-1} FLUXER_S3_ACCESS_KEY_ID: ${FLUXER_S3_ACCESS_KEY:?set FLUXER_S3_ACCESS_KEY in .env} FLUXER_S3_SECRET_ACCESS_KEY: ${FLUXER_S3_SECRET_KEY:?set FLUXER_S3_SECRET_KEY in .env} FLUXER_S3_FORCE_PATH_STYLE: "${FLUXER_S3_FORCE_PATH_STYLE:-true}" FLUXER_S3_BUCKET_CDN: ${FLUXER_S3_BUCKET_CDN:-fluxer} FLUXER_S3_BUCKET_UPLOADS: ${FLUXER_S3_BUCKET_UPLOADS:-fluxer-uploads} FLUXER_S3_BUCKET_REPORTS: ${FLUXER_S3_BUCKET_REPORTS:-fluxer-reports} FLUXER_S3_BUCKET_HARVESTS: ${FLUXER_S3_BUCKET_HARVESTS:-fluxer-harvests} FLUXER_API_PRESIGNED_HARVEST_DOWNLOADS_ENABLED: "${FLUXER_API_PRESIGNED_HARVEST_DOWNLOADS_ENABLED:-false}" FLUXER_API_STORAGE_CHANGE_FEED_ENABLED: ${FLUXER_API_STORAGE_CHANGE_FEED_ENABLED:-} FLUXER_API_STORAGE_CHANGE_FEED_STREAM: ${FLUXER_API_STORAGE_CHANGE_FEED_STREAM:-} FLUXER_API_STORAGE_CHANGE_FEED_SKIP_BUCKETS: ${FLUXER_API_STORAGE_CHANGE_FEED_SKIP_BUCKETS:-} FLUXER_CACHE_PURGE_ADAPTER: ${FLUXER_CACHE_PURGE_ADAPTER:-} FLUXER_CACHE_PURGE_HTTP_ENDPOINT: ${FLUXER_CACHE_PURGE_HTTP_ENDPOINT:-} FLUXER_CACHE_PURGE_HTTP_TOKEN: ${FLUXER_CACHE_PURGE_HTTP_TOKEN:-} FLUXER_CACHE_PURGE_HTTP_TIMEOUT_MS: ${FLUXER_CACHE_PURGE_HTTP_TIMEOUT_MS:-} FLUXER_LIVEKIT_ENABLED: "${FLUXER_LIVEKIT_ENABLED:-true}" FLUXER_LIVEKIT_API_KEY: ${LIVEKIT_API_KEY:?set LIVEKIT_API_KEY in .env} FLUXER_LIVEKIT_API_SECRET: ${LIVEKIT_API_SECRET:?set LIVEKIT_API_SECRET in .env} FLUXER_LIVEKIT_INTERNAL_URL: ${FLUXER_LIVEKIT_INTERNAL_URL:-http://livekit:7880} FLUXER_LIVEKIT_DEFAULT_REGION: '${FLUXER_LIVEKIT_DEFAULT_REGION:-{"id":"default","name":"Default","emoji":"🌍","latitude":0,"longitude":0}}' FLUXER_LIVEKIT_URL: ${FLUXER_LIVEKIT_URL:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}:${FLUXER_PUBLIC_PORT:-443}}/livekit} FLUXER_KLIPY_API_KEY: ${FLUXER_KLIPY_API_KEY:-} FLUXER_YOUTUBE_API_KEY: ${FLUXER_YOUTUBE_API_KEY:-} FLUXER_API_UNFURL_IGNORED_HOSTS: ${FLUXER_API_UNFURL_IGNORED_HOSTS:-} FLUXER_EMAIL_ENABLED: ${FLUXER_EMAIL_ENABLED:-} FLUXER_EMAIL_PROVIDER: ${FLUXER_EMAIL_PROVIDER:-} FLUXER_EMAIL_FROM_EMAIL: ${FLUXER_EMAIL_FROM_EMAIL:-noreply@localhost} FLUXER_EMAIL_FROM_NAME: ${FLUXER_EMAIL_FROM_NAME:-} FLUXER_EMAIL_REPLY_TO_EMAIL: ${FLUXER_EMAIL_REPLY_TO_EMAIL:-} FLUXER_EMAIL_APP_BASE_URL: ${FLUXER_EMAIL_APP_BASE_URL:-} FLUXER_EMAIL_WEBHOOK_SECRET: ${FLUXER_EMAIL_WEBHOOK_SECRET:-} FLUXER_EMAIL_SMTP_HOST: ${FLUXER_EMAIL_SMTP_HOST:-} FLUXER_EMAIL_SMTP_PORT: ${FLUXER_EMAIL_SMTP_PORT:-} FLUXER_EMAIL_SMTP_USERNAME: ${FLUXER_EMAIL_SMTP_USERNAME:-} FLUXER_EMAIL_SMTP_PASSWORD: ${FLUXER_EMAIL_SMTP_PASSWORD:-} FLUXER_EMAIL_SMTP_SECURE: ${FLUXER_EMAIL_SMTP_SECURE:-} FLUXER_STRIPE_ENABLED: ${FLUXER_STRIPE_ENABLED:-} FLUXER_STRIPE_SECRET_KEY: ${FLUXER_STRIPE_SECRET_KEY:-} FLUXER_STRIPE_WEBHOOK_SECRET: ${FLUXER_STRIPE_WEBHOOK_SECRET:-} FLUXER_STRIPE_PRICES: ${FLUXER_STRIPE_PRICES:-} FLUXER_STRIPE_LEGACY_PRICES: ${FLUXER_STRIPE_LEGACY_PRICES:-} FLUXER_API_DONATION_PROXY_KEY: ${FLUXER_API_DONATION_PROXY_KEY:-} FLUXER_API_TRUSTED_CALLERS: ${FLUXER_API_TRUSTED_CALLERS:-} FLUXER_VISIONARIES_GUILD_ID: ${FLUXER_VISIONARIES_GUILD_ID:-} FLUXER_VISIONARIES_GUILD_VISIONARY_ROLE_ID: ${FLUXER_VISIONARIES_GUILD_VISIONARY_ROLE_ID:-} FLUXER_NCMEC_ENABLED: ${FLUXER_NCMEC_ENABLED:-} FLUXER_NCMEC_BASE_URL: ${FLUXER_NCMEC_BASE_URL:-} FLUXER_NCMEC_USERNAME: ${FLUXER_NCMEC_USERNAME:-} FLUXER_NCMEC_PASSWORD: ${FLUXER_NCMEC_PASSWORD:-} FLUXER_NCMEC_REPORTER_EMAIL: ${FLUXER_NCMEC_REPORTER_EMAIL:-} FLUXER_CLAMAV_ENABLED: ${FLUXER_CLAMAV_ENABLED:-} FLUXER_CLAMAV_HOST: ${FLUXER_CLAMAV_HOST:-} FLUXER_CLAMAV_PORT: ${FLUXER_CLAMAV_PORT:-} FLUXER_CLAMAV_FAIL_OPEN: ${FLUXER_CLAMAV_FAIL_OPEN:-} FLUXER_APP_PRODUCT_NAME: ${FLUXER_APP_PRODUCT_NAME:-} FLUXER_APP_ICON_URL: ${FLUXER_APP_ICON_URL:-} FLUXER_APP_SYMBOL_URL: ${FLUXER_APP_SYMBOL_URL:-} FLUXER_APP_LOGO_URL: ${FLUXER_APP_LOGO_URL:-} FLUXER_APP_WORDMARK_URL: ${FLUXER_APP_WORDMARK_URL:-} FLUXER_APP_FAVICON_URL: ${FLUXER_APP_FAVICON_URL:-} FLUXER_APP_THEME_COLOR: ${FLUXER_APP_THEME_COLOR:-} FLUXER_APP_STATUS_PAGE_URL: ${FLUXER_APP_STATUS_PAGE_URL:-} FLUXER_APP_STATUS_PAGE_INCIDENT_HISTORY_URL: ${FLUXER_APP_STATUS_PAGE_INCIDENT_HISTORY_URL:-} FLUXER_INSTANCE_SETUP_CONFIGURED: ${FLUXER_INSTANCE_SETUP_CONFIGURED:-} FLUXER_AUTO_JOIN_INVITE_CODE: ${FLUXER_AUTO_JOIN_INVITE_CODE:-} FLUXER_DISCOVERY_ENABLED: ${FLUXER_DISCOVERY_ENABLED:-} FLUXER_DISCOVERY_MIN_MEMBER_COUNT: ${FLUXER_DISCOVERY_MIN_MEMBER_COUNT:-} FLUXER_DELETION_GRACE_PERIOD_HOURS: ${FLUXER_DELETION_GRACE_PERIOD_HOURS:-} FLUXER_API_WORKER_LANE_CONCURRENCY_OVERRIDES: ${FLUXER_API_WORKER_LANE_CONCURRENCY_OVERRIDES:-} FLUXER_AUTH_BLUESKY_ENABLED: ${FLUXER_AUTH_BLUESKY_ENABLED:-} FLUXER_AUTH_BLUESKY_CLIENT_NAME: ${FLUXER_AUTH_BLUESKY_CLIENT_NAME:-} FLUXER_AUTH_BLUESKY_CLIENT_URI: ${FLUXER_AUTH_BLUESKY_CLIENT_URI:-} FLUXER_AUTH_BLUESKY_LOGO_URI: ${FLUXER_AUTH_BLUESKY_LOGO_URI:-} FLUXER_AUTH_BLUESKY_TOS_URI: ${FLUXER_AUTH_BLUESKY_TOS_URI:-} FLUXER_AUTH_BLUESKY_POLICY_URI: ${FLUXER_AUTH_BLUESKY_POLICY_URI:-} FLUXER_AUTH_BLUESKY_KEYS: ${FLUXER_AUTH_BLUESKY_KEYS:-} FLUXER_PUSH_APNS_ENABLED: ${FLUXER_PUSH_APNS_ENABLED:-} FLUXER_PUSH_APNS_TEAM_ID: ${FLUXER_PUSH_APNS_TEAM_ID:-} FLUXER_PUSH_APNS_KEY_ID: ${FLUXER_PUSH_APNS_KEY_ID:-} FLUXER_PUSH_APNS_PRIVATE_KEY: ${FLUXER_PUSH_APNS_PRIVATE_KEY:-} FLUXER_PUSH_APNS_PRIVATE_KEY_PATH: ${FLUXER_PUSH_APNS_PRIVATE_KEY_PATH:-} FLUXER_PUSH_APNS_APPS: ${FLUXER_PUSH_APNS_APPS:-} FLUXER_SUDO_MODE_SECRET: ${FLUXER_SUDO_MODE_SECRET:?set FLUXER_SUDO_MODE_SECRET in .env} FLUXER_CONNECTION_INITIATION_SECRET: ${FLUXER_CONNECTION_INITIATION_SECRET:?set FLUXER_CONNECTION_INITIATION_SECRET in .env} FLUXER_SSO_ALLOW_PRIVATE_ADDRESSES: ${FLUXER_SSO_ALLOW_PRIVATE_ADDRESSES:-} FLUXER_VAPID_PUBLIC_KEY: ${FLUXER_VAPID_PUBLIC_KEY:?set FLUXER_VAPID_PUBLIC_KEY in .env} FLUXER_VAPID_PRIVATE_KEY: ${FLUXER_VAPID_PRIVATE_KEY:?set FLUXER_VAPID_PRIVATE_KEY in .env} FLUXER_VAPID_EMAIL: ${FLUXER_VAPID_EMAIL:-admin@${FLUXER_DOMAIN}} FLUXER_PASSKEY_RP_ID: ${FLUXER_PASSKEY_RP_ID:-${FLUXER_DOMAIN}} FLUXER_PASSKEY_RP_NAME: ${FLUXER_PASSKEY_RP_NAME:-} FLUXER_PASSKEY_ADDITIONAL_ALLOWED_ORIGINS: ${FLUXER_PASSKEY_ADDITIONAL_ALLOWED_ORIGINS:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}} FLUXER_GATEWAY_RPC_AUTH_TOKEN: ${FLUXER_GATEWAY_RPC_AUTH_TOKEN:?set FLUXER_GATEWAY_RPC_AUTH_TOKEN in .env} FLUXER_MEDIA_PROXY_SECRET_KEY: ${FLUXER_MEDIA_PROXY_SECRET_KEY:?set FLUXER_MEDIA_PROXY_SECRET_KEY in .env} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64:?set FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64 in .env} FLUXER_MEDIA_PROXY_ATTACHMENT_URL_SECRETS_BASE64: ${FLUXER_MEDIA_PROXY_ATTACHMENT_URL_SECRETS_BASE64:-} FLUXER_ADMIN_SECRET_KEY_BASE: ${FLUXER_ADMIN_SECRET_KEY_BASE:?set FLUXER_ADMIN_SECRET_KEY_BASE in .env} FLUXER_ADMIN_OAUTH_CLIENT_SECRET: ${FLUXER_ADMIN_OAUTH_CLIENT_SECRET:?set FLUXER_ADMIN_OAUTH_CLIENT_SECRET in .env} FLUXER_INTERNAL_API_ENDPOINT: http://api:8080 FLUXER_INTERNAL_MEDIA_PROXY_ENDPOINT: http://media-proxy:8080 FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}/media} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_MAX_BODY_BYTES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_MAX_BODY_BYTES:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_TOKEN_TTL_SECS: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_TOKEN_TTL_SECS:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_KEEP_DIRECT_COUNTRIES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_KEEP_DIRECT_COUNTRIES:-} x-fluxer-service: &fluxer-service restart: ${FLUXER_RESTART_POLICY:-unless-stopped} networks: [fluxer] x-fluxer-app-healthcheck: &fluxer-app-healthcheck interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_APP_HEALTHCHECK_RETRIES:-30} start_period: ${FLUXER_APP_HEALTHCHECK_START_PERIOD:-90s} start_interval: 1s x-fluxer-svc-healthcheck: &fluxer-svc-healthcheck <<: *fluxer-app-healthcheck start_period: ${FLUXER_SVC_HEALTHCHECK_START_PERIOD:-60s} test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/8090 && printf 'GET /_health HTTP/1.0\\r\\n\\r\\n' >&3 && head -n 1 <&3 | grep -q ' 200 '"] services: edge: <<: *fluxer-service image: ${FLUXER_CADDY_IMAGE:-caddy:2.11-alpine} deploy: resources: limits: memory: ${FLUXER_CADDY_MEMORY_LIMIT:-256mb} ports: - "${FLUXER_HTTP_PORT:-80}:80" - "${FLUXER_HTTPS_PORT:-443}:443" - "${FLUXER_HTTPS_PORT:-443}:443/udp" environment: FLUXER_EDGE_SITE_ADDRESS: ${FLUXER_EDGE_SITE_ADDRESS:-${FLUXER_CADDY_SITE_ADDRESS:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN:?set FLUXER_DOMAIN in .env}}} FLUXER_EDGE_TRUSTED_PROXIES: ${FLUXER_EDGE_TRUSTED_PROXIES:-private_ranges} FLUXER_EDGE_ENCODE: ${FLUXER_EDGE_ENCODE:-zstd gzip} FLUXER_ADMIN_BASE_PATH: ${FLUXER_ADMIN_BASE_PATH:-/admin} volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - edge-data:/data - edge-config:/config healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:2019/config/"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} depends_on: api: {condition: service_started} gateway: {condition: service_healthy} media-proxy: {condition: service_started} static-proxy: {condition: service_started} admin: {condition: service_started} postgres: <<: *fluxer-service image: ${FLUXER_POSTGRES_IMAGE:-postgres:16-alpine} deploy: resources: limits: memory: ${FLUXER_POSTGRES_MEMORY_LIMIT:-5gb} reservations: memory: ${FLUXER_POSTGRES_MEMORY_RESERVATION:-3gb} command: > postgres -c max_connections=${FLUXER_POSTGRES_SERVER_MAX_CONNECTIONS:-150} -c shared_buffers=${FLUXER_POSTGRES_SHARED_BUFFERS:-512MB} -c effective_cache_size=${FLUXER_POSTGRES_EFFECTIVE_CACHE_SIZE:-2GB} -c work_mem=${FLUXER_POSTGRES_WORK_MEM:-8MB} -c maintenance_work_mem=${FLUXER_POSTGRES_MAINTENANCE_WORK_MEM:-256MB} -c autovacuum_work_mem=${FLUXER_POSTGRES_AUTOVACUUM_WORK_MEM:-128MB} -c random_page_cost=${FLUXER_POSTGRES_RANDOM_PAGE_COST:-1.1} -c effective_io_concurrency=${FLUXER_POSTGRES_EFFECTIVE_IO_CONCURRENCY:-200} -c default_statistics_target=${FLUXER_POSTGRES_DEFAULT_STATISTICS_TARGET:-200} -c jit=${FLUXER_POSTGRES_JIT:-off} -c min_wal_size=${FLUXER_POSTGRES_MIN_WAL_SIZE:-512MB} -c max_wal_size=${FLUXER_POSTGRES_MAX_WAL_SIZE:-2GB} -c checkpoint_completion_target=${FLUXER_POSTGRES_CHECKPOINT_COMPLETION_TARGET:-0.9} -c wal_buffers=${FLUXER_POSTGRES_WAL_BUFFERS:-16MB} -c wal_compression=${FLUXER_POSTGRES_WAL_COMPRESSION:-zstd} -c bgwriter_delay=${FLUXER_POSTGRES_BGWRITER_DELAY:-50ms} -c bgwriter_lru_maxpages=${FLUXER_POSTGRES_BGWRITER_LRU_MAXPAGES:-1000} -c autovacuum_vacuum_scale_factor=${FLUXER_POSTGRES_AUTOVACUUM_VACUUM_SCALE_FACTOR:-0.05} -c autovacuum_analyze_scale_factor=${FLUXER_POSTGRES_AUTOVACUUM_ANALYZE_SCALE_FACTOR:-0.02} -c autovacuum_vacuum_cost_limit=${FLUXER_POSTGRES_AUTOVACUUM_VACUUM_COST_LIMIT:-2000} -c track_io_timing=${FLUXER_POSTGRES_TRACK_IO_TIMING:-on} -c shared_preload_libraries=${FLUXER_POSTGRES_SHARED_PRELOAD_LIBRARIES:-pg_stat_statements} shm_size: ${FLUXER_POSTGRES_SHM_SIZE:-1gb} environment: POSTGRES_DB: ${FLUXER_POSTGRES_DATABASE:-fluxer} POSTGRES_USER: ${FLUXER_POSTGRES_USERNAME:-fluxer} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env} volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} valkey: <<: *fluxer-service image: ${FLUXER_VALKEY_IMAGE:-valkey/valkey:9.1-alpine} deploy: resources: limits: memory: ${FLUXER_VALKEY_MEMORY_LIMIT:-256mb} command: ["valkey-server", "--appendonly", "yes", "--appendfsync", "${FLUXER_VALKEY_APPENDFSYNC:-everysec}", "--dir", "/data", "--maxmemory", "${FLUXER_VALKEY_MAXMEMORY:-192mb}", "--maxmemory-policy", "${FLUXER_VALKEY_MAXMEMORY_POLICY:-noeviction}"] volumes: - valkey-data:/data healthcheck: test: ["CMD", "valkey-cli", "ping"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} nats: <<: *fluxer-service image: ${FLUXER_NATS_IMAGE:-nats:2.14-alpine} deploy: resources: limits: memory: ${FLUXER_NATS_MEMORY_LIMIT:-256mb} command: ["-js", "-sd", "/data", "-m", "8222"] volumes: - nats-data:/data healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8222/healthz"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} meilisearch: <<: *fluxer-service image: ${FLUXER_MEILISEARCH_IMAGE:-getmeili/meilisearch:v1.53} deploy: resources: limits: memory: ${FLUXER_MEILISEARCH_MEMORY_LIMIT:-1536mb} environment: MEILI_ENV: ${FLUXER_MEILISEARCH_ENV:-production} MEILI_NO_ANALYTICS: "${FLUXER_MEILISEARCH_NO_ANALYTICS:-true}" MEILI_UPGRADE_DB: "true" MEILI_MAX_INDEXING_MEMORY: ${FLUXER_MEILISEARCH_MAX_INDEXING_MEMORY:-256mb} MEILI_MAX_INDEXING_THREADS: ${FLUXER_MEILISEARCH_MAX_INDEXING_THREADS:-2} MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY in .env} volumes: - meilisearch-data:/meili_data healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:7700/health"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} seaweedfs: <<: *fluxer-service image: ${FLUXER_SEAWEEDFS_IMAGE:-chrislusf/seaweedfs:4.47} deploy: resources: limits: memory: ${FLUXER_SEAWEEDFS_MEMORY_LIMIT:-2gb} environment: GOMEMLIMIT: ${FLUXER_SEAWEEDFS_GOMEMLIMIT:-1536MiB} WEED_MASTER_VOLUME_GROWTH_COPY_1: ${FLUXER_SEAWEEDFS_VOLUME_GROWTH:-1} command: ["server", "-s3", "-dir=/data", "-master.telemetry=${FLUXER_SEAWEEDFS_TELEMETRY:-false}"] volumes: - seaweedfs-data:/data healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8333/healthz"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_SEAWEEDFS_HEALTHCHECK_RETRIES:-20} start_period: ${FLUXER_SEAWEEDFS_HEALTHCHECK_START_PERIOD:-60s} seaweedfs-init: image: ${FLUXER_SEAWEEDFS_IMAGE:-chrislusf/seaweedfs:4.47} deploy: resources: limits: memory: ${FLUXER_SEAWEEDFS_INIT_MEMORY_LIMIT:-128mb} networks: [fluxer] depends_on: seaweedfs: {condition: service_healthy} restart: "no" environment: FLUXER_S3_ACCESS_KEY: ${FLUXER_S3_ACCESS_KEY:?set FLUXER_S3_ACCESS_KEY in .env} FLUXER_S3_SECRET_KEY: ${FLUXER_S3_SECRET_KEY:?set FLUXER_S3_SECRET_KEY in .env} FLUXER_S3_BUCKET_CDN: ${FLUXER_S3_BUCKET_CDN:-fluxer} FLUXER_S3_BUCKET_UPLOADS: ${FLUXER_S3_BUCKET_UPLOADS:-fluxer-uploads} FLUXER_S3_BUCKET_REPORTS: ${FLUXER_S3_BUCKET_REPORTS:-fluxer-reports} FLUXER_S3_BUCKET_HARVESTS: ${FLUXER_S3_BUCKET_HARVESTS:-fluxer-harvests} FLUXER_SEAWEEDFS_INIT_ATTEMPTS: ${FLUXER_SEAWEEDFS_INIT_ATTEMPTS:-60} entrypoint: - /bin/sh - -c - > buckets="$$FLUXER_S3_BUCKET_CDN $$FLUXER_S3_BUCKET_UPLOADS $$FLUXER_S3_BUCKET_REPORTS $$FLUXER_S3_BUCKET_HARVESTS"; missing="$$buckets"; for attempt in $$(seq 1 $$FLUXER_SEAWEEDFS_INIT_ATTEMPTS); do if ! nc -z seaweedfs 9333 2>/dev/null; then sleep 2; continue; fi; listed=$$(echo "s3.bucket.list" | timeout 10 weed shell -master=seaweedfs:9333 2>&1); missing=""; for b in $$buckets; do echo "$$listed" | grep -q "^[[:space:]]*$$b[[:space:]]" || missing="$${missing:+$$missing }$$b"; done; if [ -z "$$missing" ]; then if ! echo "s3.configure -user=fluxer -access_key=$$FLUXER_S3_ACCESS_KEY -secret_key=$$FLUXER_S3_SECRET_KEY -actions=Admin,Read,Write,List,Tagging -apply" | timeout 10 weed shell -master=seaweedfs:9333 >/dev/null 2>&1; then echo "seaweedfs-init could not configure the S3 identity" >&2; exit 1; fi; echo "buckets ready"; exit 0; fi; for b in $$missing; do echo "s3.bucket.create -name $$b" | timeout 10 weed shell -master=seaweedfs:9333 >/dev/null 2>&1; done; sleep 2; done; echo "seaweedfs-init could not verify buckets: $$missing" >&2; exit 1; livekit: <<: *fluxer-service image: ${FLUXER_LIVEKIT_IMAGE:-livekit/livekit-server:v1.12.0} deploy: resources: limits: memory: ${FLUXER_LIVEKIT_MEMORY_LIMIT:-512mb} environment: LIVEKIT_KEYS: "${LIVEKIT_API_KEY:?set LIVEKIT_API_KEY in .env}: ${LIVEKIT_API_SECRET:?set LIVEKIT_API_SECRET in .env}" LIVEKIT_CONFIG: | port: 7880 log_level: ${FLUXER_LIVEKIT_LOG_LEVEL:-info} rtc: tcp_port: ${FLUXER_LIVEKIT_TCP_PORT:-7881} udp_port: ${FLUXER_LIVEKIT_UDP_PORT:-7882} use_external_ip: ${FLUXER_LIVEKIT_USE_EXTERNAL_IP:-true} node_ip: "${FLUXER_LIVEKIT_NODE_IP:-}" stun_servers: - ${FLUXER_LIVEKIT_STUN_PRIMARY:-stun.l.google.com:19302} - ${FLUXER_LIVEKIT_STUN_SECONDARY:-stun1.l.google.com:19302} webhook: api_key: ${LIVEKIT_API_KEY:?set LIVEKIT_API_KEY in .env} urls: - http://api:8080/webhooks/livekit ports: - "${FLUXER_LIVEKIT_TCP_PORT:-7881}:${FLUXER_LIVEKIT_TCP_PORT:-7881}" - "${FLUXER_LIVEKIT_UDP_PORT:-7882}:${FLUXER_LIVEKIT_UDP_PORT:-7882}/udp" healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:7880/"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} api: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-api:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_API_MEMORY_LIMIT:-2560mb} reservations: memory: ${FLUXER_API_MEMORY_RESERVATION:-1gb} environment: <<: *fluxer-env FLUXER_API_PORT: "8080" NODE_OPTIONS: --enable-source-maps${FLUXER_API_NODE_HEAP_MB:+ --max-old-space-size=$FLUXER_API_NODE_HEAP_MB}${FLUXER_API_NODE_OPTIONS:+ $FLUXER_API_NODE_OPTIONS} NODE_EXTRA_CA_CERTS: ${FLUXER_NODE_EXTRA_CA_CERTS:-/etc/ssl/certs/ca-certificates.crt} FLUXER_POSTGRES_MAX_CONNECTIONS: "${FLUXER_API_POSTGRES_MAX_CONNECTIONS:-25}" FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED: "${FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED:-true}" healthcheck: test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:8080/_health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""] <<: *fluxer-app-healthcheck depends_on: postgres: {condition: service_healthy} valkey: {condition: service_healthy} nats: {condition: service_healthy} meilisearch: {condition: service_healthy} seaweedfs-init: {condition: service_completed_successfully} gifs: {condition: service_healthy} gifs-shard: {condition: service_healthy} snowflakes: {condition: service_healthy} snowflakes-shard: {condition: service_healthy} messages: {condition: service_healthy} messages-shard: {condition: service_healthy} users: {condition: service_healthy} users-shard: {condition: service_healthy} worker: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-api:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_WORKER_MEMORY_LIMIT:-2560mb} reservations: memory: ${FLUXER_WORKER_MEMORY_RESERVATION:-1gb} command: ["node", "dist/WorkerEntrypoint.js"] environment: <<: *fluxer-env NODE_OPTIONS: --enable-source-maps${FLUXER_WORKER_NODE_HEAP_MB:+ --max-old-space-size=$FLUXER_WORKER_NODE_HEAP_MB}${FLUXER_WORKER_NODE_OPTIONS:+ $FLUXER_WORKER_NODE_OPTIONS} NODE_EXTRA_CA_CERTS: ${FLUXER_NODE_EXTRA_CA_CERTS:-/etc/ssl/certs/ca-certificates.crt} FLUXER_API_WORKER_MODE: all_lanes FLUXER_API_WORKER_ENABLE_CRON_SCHEDULER: "true" FLUXER_POSTGRES_MAX_CONNECTIONS: "${FLUXER_WORKER_POSTGRES_MAX_CONNECTIONS:-25}" healthcheck: test: ["CMD", "node", "-e", "const age=Date.now()-require('node:fs').statSync('/tmp/fluxer-worker-heartbeat').mtimeMs;if(age>30000){console.error('worker heartbeat is '+Math.round(age)+'ms old');process.exit(1)}"] <<: *fluxer-app-healthcheck retries: ${FLUXER_WORKER_HEALTHCHECK_RETRIES:-3} depends_on: postgres: {condition: service_healthy} valkey: {condition: service_healthy} nats: {condition: service_healthy} seaweedfs-init: {condition: service_completed_successfully} snowflakes-shard: {condition: service_healthy} messages-shard: {condition: service_healthy} users-shard: {condition: service_healthy} gateway: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gateway:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_GATEWAY_MEMORY_LIMIT:-1gb} reservations: memory: ${FLUXER_GATEWAY_MEMORY_RESERVATION:-384mb} environment: <<: *fluxer-env FLUXER_GATEWAY_PORT: "8080" FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT: ${FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT:-${FLUXER_MEDIA_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}/media}} FLUXER_GATEWAY_STATIC_CDN_ENDPOINT: ${FLUXER_GATEWAY_STATIC_CDN_ENDPOINT:-${FLUXER_STATIC_CDN_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}}} FLUXER_GATEWAY_LOGGER_LEVEL: ${FLUXER_GATEWAY_LOGGER_LEVEL:-} LOGGER_LEVEL: ${LOGGER_LEVEL:-} FLUXER_GATEWAY_PUSH_ENABLED: ${FLUXER_GATEWAY_PUSH_ENABLED:-} FLUXER_GATEWAY_PUSH_ENROLLED_CLEAR_NOTIFICATIONS_ENABLED: ${FLUXER_GATEWAY_PUSH_ENROLLED_CLEAR_NOTIFICATIONS_ENABLED:-} FLUXER_GATEWAY_PUSH_OUTBOX_REQUEST_TIMEOUT_MS: ${FLUXER_GATEWAY_PUSH_OUTBOX_REQUEST_TIMEOUT_MS:-} FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES: ${FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES:-} FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES: ${FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES:-} FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY: ${FLUXER_GATEWAY_HTTP_RPC_MAX_CONCURRENCY:-} FLUXER_GATEWAY_NATS_RPC_MAX_HANDLERS: ${FLUXER_GATEWAY_NATS_RPC_MAX_HANDLERS:-} FLUXER_GATEWAY_HTTP_FAILURE_THRESHOLD: ${FLUXER_GATEWAY_HTTP_FAILURE_THRESHOLD:-} FLUXER_GATEWAY_HTTP_RECOVERY_TIMEOUT_MS: ${FLUXER_GATEWAY_HTTP_RECOVERY_TIMEOUT_MS:-} FLUXER_ERLANG_COOKIE: ${FLUXER_ERLANG_COOKIE:?set FLUXER_ERLANG_COOKIE in .env} FLUXER_ERLANG_SCHEDULERS: ${FLUXER_ERLANG_SCHEDULERS:-} FLUXER_ERLANG_SCHEDULERS_MIN: ${FLUXER_ERLANG_SCHEDULERS_MIN:-} FLUXER_ERLANG_SCHEDULERS_MAX: ${FLUXER_ERLANG_SCHEDULERS_MAX:-} FLUXER_ERLANG_DIRTY_CPU_SCHEDULERS: ${FLUXER_ERLANG_DIRTY_CPU_SCHEDULERS:-} healthcheck: test: ["CMD", "curl", "-fsS", "-o", "/dev/null", "http://127.0.0.1:8080/_health/ready"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_APP_HEALTHCHECK_RETRIES:-30} start_period: ${FLUXER_APP_HEALTHCHECK_START_PERIOD:-90s} depends_on: nats: {condition: service_healthy} valkey: {condition: service_healthy} media-proxy: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-media-proxy:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_MEDIA_PROXY_MEMORY_LIMIT:-512mb} environment: <<: *fluxer-env FLUXER_MEDIA_PROXY_PORT: "8080" FLUXER_MEDIA_PROXY_MODE: upload FLUXER_MEDIA_PROXY_STORAGE_BACKEND: s3 FLUXER_MEDIA_PROXY_CORS_MODE: ${FLUXER_MEDIA_PROXY_CORS_MODE:-} FLUXER_MEDIA_PROXY_CORS_ALLOWED_ORIGINS: ${FLUXER_MEDIA_PROXY_CORS_ALLOWED_ORIGINS:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}:${FLUXER_PUBLIC_PORT:-443}}} FLUXER_MEDIA_PROXY_ATTACHMENT_SIGNATURE_MODE: ${FLUXER_MEDIA_PROXY_ATTACHMENT_SIGNATURE_MODE:-} FLUXER_MEDIA_PROXY_READ_ONLY: ${FLUXER_MEDIA_PROXY_READ_ONLY:-} FLUXER_MEDIA_PROXY_NSFW_THRESHOLD: ${FLUXER_MEDIA_PROXY_NSFW_THRESHOLD:-} FLUXER_NSFW_SERVICE_ENDPOINT: ${FLUXER_NSFW_SERVICE_ENDPOINT:-} FLUXER_MEDIA_PROXY_MAX_NATIVE_TRANSFORMS: ${FLUXER_MEDIA_PROXY_MAX_NATIVE_TRANSFORMS:-} FLUXER_MEDIA_PROXY_WORKER_QUEUE_CAPACITY: ${FLUXER_MEDIA_PROXY_WORKER_QUEUE_CAPACITY:-} FLUXER_MEDIA_PROXY_MAX_ENCODE_DURATION_MS: ${FLUXER_MEDIA_PROXY_MAX_ENCODE_DURATION_MS:-} FLUXER_MEDIA_PROXY_MAX_ENCODE_FRAMES: ${FLUXER_MEDIA_PROXY_MAX_ENCODE_FRAMES:-} FLUXER_MEDIA_PROXY_TRANSFORM_TIMEOUT_MS: ${FLUXER_MEDIA_PROXY_TRANSFORM_TIMEOUT_MS:-} FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_BYTES: ${FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_BYTES:-} FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_MAX_ENTRY_BYTES: ${FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_MAX_ENTRY_BYTES:-} FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_TTL_MS: ${FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_TTL_MS:-} FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS: ${FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS:-} FLUXER_MEDIA_PROXY_SHUTDOWN_GRACE_MS: ${FLUXER_MEDIA_PROXY_SHUTDOWN_GRACE_MS:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_S3_TIMEOUT_MS: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_S3_TIMEOUT_MS:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_BUFFERED_RETRY_BYTES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_BUFFERED_RETRY_BYTES:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_BUFFERED_RETRY_TOTAL_BYTES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_BUFFERED_RETRY_TOTAL_BYTES:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_DIR: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_DIR:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_CHUNK_BYTES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_CHUNK_BYTES:-} FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_MAX_TOTAL_BYTES: ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SPOOL_MAX_TOTAL_BYTES:-} FLUXER_S3_SESSION_TOKEN: ${FLUXER_S3_SESSION_TOKEN:-} FLUXER_S3_READ_ENDPOINT: ${FLUXER_S3_READ_ENDPOINT:-} FLUXER_S3_READ_BUCKET: ${FLUXER_S3_READ_BUCKET:-} FLUXER_S3_READ_BUCKET_STYLE: ${FLUXER_S3_READ_BUCKET_STYLE:-} FLUXER_S3_READ_SIGNED: "${FLUXER_S3_READ_SIGNED:-true}" depends_on: seaweedfs-init: {condition: service_completed_successfully} nats: {condition: service_healthy} push: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-push:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_PUSH_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_PUSH_SERVICE_QUEUE_CAPACITY: ${FLUXER_PUSH_SERVICE_QUEUE_CAPACITY:-} FLUXER_PUSH_SERVICE_SEND_CONCURRENCY: ${FLUXER_PUSH_SERVICE_SEND_CONCURRENCY:-} FLUXER_PUSH_SERVICE_APNS_BASE_URL: ${FLUXER_PUSH_SERVICE_APNS_BASE_URL:-} FLUXER_PUSH_SERVICE_FCM_BASE_URL: ${FLUXER_PUSH_SERVICE_FCM_BASE_URL:-} FLUXER_PUSH_SERVICE_MANAGED_RELAY_HOSTS: ${FLUXER_PUSH_SERVICE_MANAGED_RELAY_HOSTS:-} FLUXER_PUSH_SERVICE_OWN_RELAY_HOSTS: ${FLUXER_PUSH_SERVICE_OWN_RELAY_HOSTS:-} FLUXER_PUSH_SERVICE_RELAY_CONSENT_ACCEPTED: ${FLUXER_PUSH_SERVICE_RELAY_CONSENT_ACCEPTED:-} FLUXER_PUSH_APNS_DEFAULT_ENVIRONMENT: ${FLUXER_PUSH_APNS_DEFAULT_ENVIRONMENT:-} FLUXER_PUSH_FCM_ENABLED: ${FLUXER_PUSH_FCM_ENABLED:-} FLUXER_PUSH_FCM_PROJECT_ID: ${FLUXER_PUSH_FCM_PROJECT_ID:-} FLUXER_PUSH_FCM_CLIENT_EMAIL: ${FLUXER_PUSH_FCM_CLIENT_EMAIL:-} FLUXER_PUSH_FCM_PRIVATE_KEY: ${FLUXER_PUSH_FCM_PRIVATE_KEY:-} FLUXER_PUSH_FCM_PRIVATE_KEY_PATH: ${FLUXER_PUSH_FCM_PRIVATE_KEY_PATH:-} FLUXER_PUSH_FCM_SERVICE_ACCOUNT_JSON_PATH: ${FLUXER_PUSH_FCM_SERVICE_ACCOUNT_JSON_PATH:-} FLUXER_PUSH_FCM_TOKEN_URI: ${FLUXER_PUSH_FCM_TOKEN_URI:-} FLUXER_PUSH_FCM_APPS: ${FLUXER_PUSH_FCM_APPS:-} healthcheck: test: ["CMD", "/usr/local/bin/fluxer-push", "healthcheck"] <<: *fluxer-app-healthcheck start_period: ${FLUXER_SVC_HEALTHCHECK_START_PERIOD:-60s} depends_on: nats: {condition: service_healthy} api: {condition: service_healthy} static-proxy: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-static:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_STATIC_PROXY_MEMORY_LIMIT:-256mb} healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8080/avatars/0.png"] interval: ${FLUXER_HEALTHCHECK_INTERVAL:-10s} timeout: ${FLUXER_HEALTHCHECK_TIMEOUT:-5s} retries: ${FLUXER_HEALTHCHECK_RETRIES:-10} app-proxy: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-app-proxy-self-hosted:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_APP_PROXY_MEMORY_LIMIT:-256mb} environment: RUST_LOG: ${RUST_LOG:-} FLUXER_APP_PROXY_PORT: "8080" FLUXER_BASE_DOMAIN: ${FLUXER_DOMAIN:?set FLUXER_DOMAIN in .env} FLUXER_PUBLIC_SCHEME: ${FLUXER_PUBLIC_SCHEME:-https} FLUXER_PUBLIC_PORT: ${FLUXER_PUBLIC_PORT:-443} FLUXER_PUBLIC_ORIGIN: ${FLUXER_PUBLIC_ORIGIN:-} FLUXER_TRUST_CLIENT_IP_HEADER: "${FLUXER_TRUST_CLIENT_IP_HEADER:-true}" FLUXER_CLIENT_IP_HEADER_NAME: ${FLUXER_CLIENT_IP_HEADER_NAME:-} FLUXER_GEOIP_DB_PATH: ${FLUXER_GEOIP_DB_PATH:-} FLUXER_S3_ENDPOINT: ${FLUXER_S3_ENDPOINT:-http://seaweedfs:8333} FLUXER_S3_PUBLIC_ENDPOINT: ${FLUXER_S3_PUBLIC_ENDPOINT:-} FLUXER_S3_REGION: ${FLUXER_S3_REGION:-us-east-1} FLUXER_S3_ACCESS_KEY_ID: ${FLUXER_S3_ACCESS_KEY:?set FLUXER_S3_ACCESS_KEY in .env} FLUXER_S3_SECRET_ACCESS_KEY: ${FLUXER_S3_SECRET_KEY:?set FLUXER_S3_SECRET_KEY in .env} FLUXER_S3_BUCKET_UPLOADS: ${FLUXER_S3_BUCKET_UPLOADS:-} FLUXER_STATIC_CDN_ENDPOINT: ${FLUXER_STATIC_CDN_ENDPOINT:-} DISCOVERY_UPSTREAM_URL: http://edge:8088/.well-known/fluxer DISCOVERY_REFRESH_INTERVAL_MS: ${DISCOVERY_REFRESH_INTERVAL_MS:-} PUBLIC_BOOTSTRAP_API_ENDPOINT: /api PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT: ${PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}/api} FLUXER_APP_PROXY_INDEX_UPSTREAM_URL: ${FLUXER_APP_PROXY_INDEX_UPSTREAM_URL:-} FLUXER_APP_PROXY_SAME_ORIGIN_HOSTS: ${FLUXER_APP_PROXY_SAME_ORIGIN_HOSTS:-} FLUXER_APP_PROXY_MANIFEST_SCOPE_EXTENSIONS: ${FLUXER_APP_PROXY_MANIFEST_SCOPE_EXTENSIONS:-} FLUXER_CSP_EXTRA_DEFAULT_SRC: ${FLUXER_CSP_EXTRA_DEFAULT_SRC:-} FLUXER_CSP_EXTRA_CONNECT_SRC: ${FLUXER_CSP_EXTRA_CONNECT_SRC:-} FLUXER_CSP_EXTRA_IMG_SRC: ${FLUXER_CSP_EXTRA_IMG_SRC:-} FLUXER_CSP_EXTRA_MEDIA_SRC: ${FLUXER_CSP_EXTRA_MEDIA_SRC:-} FLUXER_CSP_EXTRA_FONT_SRC: ${FLUXER_CSP_EXTRA_FONT_SRC:-} FLUXER_CSP_EXTRA_SCRIPT_SRC: ${FLUXER_CSP_EXTRA_SCRIPT_SRC:-} FLUXER_CSP_EXTRA_STYLE_SRC: ${FLUXER_CSP_EXTRA_STYLE_SRC:-} FLUXER_CSP_EXTRA_FRAME_SRC: ${FLUXER_CSP_EXTRA_FRAME_SRC:-} FLUXER_CSP_EXTRA_WORKER_SRC: ${FLUXER_CSP_EXTRA_WORKER_SRC:-} FLUXER_CSP_EXTRA_MANIFEST_SRC: ${FLUXER_CSP_EXTRA_MANIFEST_SRC:-} FLUXER_CSP_REPORT_URI: ${FLUXER_CSP_REPORT_URI:-} depends_on: api: {condition: service_healthy} edge: {condition: service_healthy} snowflakes: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-snowflakes:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_SNOWFLAKES_MEMORY_LIMIT:-128mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: snowflakes FLUXER_SVC_MODE: router healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} snowflakes-shard: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-snowflakes:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_SNOWFLAKES_SHARD_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: snowflakes FLUXER_SVC_MODE: shard FLUXER_SVC_SHARD_ID: "0" healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} users: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-users:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_USERS_MEMORY_LIMIT:-128mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: users FLUXER_SVC_MODE: router healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} users-shard: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-users:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_USERS_SHARD_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: users FLUXER_SVC_MODE: shard FLUXER_SVC_SHARD_ID: "0" FLUXER_POSTGRES_MAX_CONNECTIONS: "${FLUXER_USERS_SHARD_POSTGRES_MAX_CONNECTIONS:-20}" healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} postgres: {condition: service_healthy} gifs: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gifs:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_GIFS_MEMORY_LIMIT:-128mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: gifs FLUXER_SVC_MODE: router healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} gifs-shard: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gifs:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_GIFS_SHARD_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: gifs FLUXER_SVC_MODE: shard FLUXER_SVC_SHARD_ID: "0" FLUXER_GIFS_SHARD_CACHE_MAX_BYTES: ${FLUXER_GIFS_SHARD_CACHE_MAX_BYTES:-} healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} messages: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-messages:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_MESSAGES_MEMORY_LIMIT:-128mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: messages FLUXER_SVC_MODE: router healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} messages-shard: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-messages:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_MESSAGES_SHARD_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: messages FLUXER_SVC_MODE: shard FLUXER_SVC_SHARD_ID: "0" FLUXER_POSTGRES_MAX_CONNECTIONS: "${FLUXER_MESSAGES_SHARD_POSTGRES_MAX_CONNECTIONS:-20}" healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} postgres: {condition: service_healthy} unfurl: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-unfurl:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_UNFURL_MEMORY_LIMIT:-128mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: unfurl FLUXER_SVC_MODE: router healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} unfurl-shard: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-unfurl:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_UNFURL_SHARD_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_SVC_NAME: unfurl FLUXER_SVC_MODE: shard FLUXER_SVC_SHARD_ID: "0" FLUXER_MEDIA_PROXY_ENDPOINT: http://media-proxy:8080 healthcheck: *fluxer-svc-healthcheck depends_on: nats: {condition: service_healthy} admin: <<: *fluxer-service image: ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-admin:${FLUXER_IMAGE_TAG:-v1} deploy: resources: limits: memory: ${FLUXER_ADMIN_MEMORY_LIMIT:-256mb} environment: <<: *fluxer-env FLUXER_ADMIN_PORT: "8080" FLUXER_ADMIN_BASE_PATH: ${FLUXER_ADMIN_BASE_PATH:-/admin} FLUXER_API_ENDPOINT: http://api:8080 FLUXER_STATIC_CDN_ENDPOINT: ${FLUXER_STATIC_CDN_ENDPOINT:-${FLUXER_PUBLIC_ORIGIN:-${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}}} healthcheck: test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/8080 && printf 'GET /_health HTTP/1.0\\r\\n\\r\\n' >&3 && head -n 1 <&3 | grep -q ' 200 '"] <<: *fluxer-app-healthcheck start_period: ${FLUXER_SVC_HEALTHCHECK_START_PERIOD:-60s} depends_on: api: {condition: service_healthy} networks: fluxer: driver: bridge volumes: edge-data: edge-config: postgres-data: valkey-data: nats-data: meilisearch-data: seaweedfs-data: