193 أسطر
6.3 KiB
Plaintext
193 أسطر
6.3 KiB
Plaintext
# For mobile/LAN testing set PUBLIC_BASE_URL to your machine IP, not localhost.
|
|
# Example: PUBLIC_BASE_URL=http://192.168.1.12:4000
|
|
NODE_ENV=development
|
|
PORT=4000
|
|
HOST=0.0.0.0
|
|
PUBLIC_BASE_URL=http://localhost:4000
|
|
PUBLIC_APP_URL=https://oudelaa.com
|
|
RESPONSE_ENVELOPE_ENABLED=false
|
|
SWAGGER_ENABLED=true
|
|
GLOBAL_PREFIX=api/v1
|
|
# Add every frontend origin used by web/mobile debug tools.
|
|
CORS_ORIGINS=http://localhost:3000,http://192.168.1.14:3000,http://192.168.1.14:5173
|
|
MONGODB_URI=mongodb://127.0.0.1:27017/oudelaa
|
|
MONGODB_AUTO_INDEX=true
|
|
MONGODB_MIN_POOL_SIZE=5
|
|
MONGODB_MAX_POOL_SIZE=100
|
|
MONGODB_MAX_IDLE_TIME_MS=60000
|
|
MONGODB_SERVER_SELECTION_TIMEOUT_MS=10000
|
|
MONGODB_SOCKET_TIMEOUT_MS=45000
|
|
# Search keeps the same API contract. "auto" uses Atlas Search when available
|
|
# and falls back to MongoDB regex search on local/community deployments.
|
|
SEARCH_ENGINE=auto
|
|
SEARCH_ATLAS_USER_INDEX=users_search
|
|
SEARCH_ATLAS_POST_INDEX=posts_search
|
|
SEARCH_FALLBACK_ENABLED=true
|
|
SEARCH_ATLAS_RETRY_SECONDS=300
|
|
JWT_ACCESS_SECRET=change_me_access_secret
|
|
JWT_ACCESS_EXPIRES_IN=15m
|
|
JWT_REFRESH_SECRET=change_me_refresh_secret
|
|
JWT_REFRESH_EXPIRES_IN=30d
|
|
BCRYPT_SALT_ROUNDS=12
|
|
REFRESH_TOKEN_HASH_SECRET=
|
|
HTTP_BODY_LIMIT=1mb
|
|
# Controller execution deadline. Override individual long-running routes with @RequestTimeout().
|
|
HTTP_REQUEST_TIMEOUT_MS=30000
|
|
# Low-level slow-client protection and connection reuse limits.
|
|
HTTP_SERVER_REQUEST_TIMEOUT_MS=120000
|
|
HTTP_HEADERS_TIMEOUT_MS=15000
|
|
HTTP_KEEP_ALIVE_TIMEOUT_MS=5000
|
|
HTTP_MAX_REQUESTS_PER_SOCKET=1000
|
|
# Time allowed for in-flight controller requests after SIGTERM/SIGINT.
|
|
SHUTDOWN_GRACE_PERIOD_MS=30000
|
|
METRICS_EVENT_LOOP_RESOLUTION_MS=20
|
|
METRICS_EVENT_LOOP_LAG_WARN_MS=100
|
|
METRICS_MAX_ROUTES=500
|
|
MODERATION_BLOCKED_TERMS=
|
|
PASSWORD_RESET_CODE_EXPIRES_MINUTES=10
|
|
PASSWORD_RESET_MAX_ATTEMPTS=5
|
|
PASSWORD_RESET_TOKEN_SECRET=
|
|
PASSWORD_RESET_TOKEN_EXPIRES_IN=15m
|
|
EMAIL_VERIFICATION_CODE_EXPIRES_MINUTES=10
|
|
EMAIL_VERIFICATION_MAX_ATTEMPTS=5
|
|
SWAGGER_TITLE=Oudelaa API
|
|
SWAGGER_DESCRIPTION=Social media backend API documentation
|
|
SWAGGER_VERSION=1.0.0
|
|
SWAGGER_PATH=docs
|
|
LOG_LEVEL=log
|
|
REQUEST_LOGGING_ENABLED=true
|
|
FEED_CACHE_ENABLED=true
|
|
FEED_CACHE_USER_TTL_SECONDS=15
|
|
FEED_CACHE_TRENDING_TTL_SECONDS=30
|
|
FEED_CACHE_RANKING_PROFILE_TTL_SECONDS=30
|
|
FEED_TIMING_LOGS_ENABLED=false
|
|
HTTP_COMPRESSION_ENABLED=true
|
|
HTTP_COMPRESSION_THRESHOLD_BYTES=1024
|
|
|
|
REDIS_ENABLED=false
|
|
REDIS_URL=
|
|
REDIS_HOST=127.0.0.1
|
|
REDIS_PORT=6379
|
|
REDIS_USERNAME=
|
|
REDIS_PASSWORD=
|
|
REDIS_DB=0
|
|
REDIS_KEY_PREFIX=oudelaa
|
|
REDIS_SOCKET_ADAPTER_ENABLED=false
|
|
|
|
QUEUE_ENABLED=false
|
|
QUEUE_NAME=app-jobs
|
|
QUEUE_DEFAULT_ATTEMPTS=3
|
|
QUEUE_DEFAULT_BACKOFF_MS=1000
|
|
QUEUE_REMOVE_ON_COMPLETE=true
|
|
QUEUE_WORKER_CONCURRENCY=5
|
|
|
|
# Phase 1 microservice routing (false keeps the current in-process path)
|
|
NOTIFICATION_SERVICE_ENABLED=false
|
|
# The polling dispatcher is independently disabled for the current production monolith.
|
|
OUTBOX_DISPATCHER_ENABLED=false
|
|
OUTBOX_POLL_INTERVAL_MS=1000
|
|
OUTBOX_BATCH_SIZE=25
|
|
OUTBOX_MAX_ATTEMPTS=8
|
|
OUTBOX_LEASE_TIMEOUT_MS=60000
|
|
OUTBOX_RETRY_BASE_MS=1000
|
|
OUTBOX_RETRY_MAX_MS=60000
|
|
# Local development only. Production must inject non-guest credentials and TLS/amqps.
|
|
RABBITMQ_URL=amqp://guest:guest@127.0.0.1:5672
|
|
RABBITMQ_HOST=127.0.0.1
|
|
RABBITMQ_PORT=5672
|
|
RABBITMQ_USERNAME=
|
|
RABBITMQ_PASSWORD=
|
|
RABBITMQ_VHOST=/
|
|
RABBITMQ_TLS_ENABLED=false
|
|
RABBITMQ_TLS_REQUIRED=true
|
|
RABBITMQ_CA_CERT_BASE64=
|
|
RABBITMQ_CA_CERT_PATH=
|
|
RABBITMQ_CLIENT_CERT_BASE64=
|
|
RABBITMQ_CLIENT_CERT_PATH=
|
|
RABBITMQ_CLIENT_KEY_BASE64=
|
|
RABBITMQ_CLIENT_KEY_PATH=
|
|
RABBITMQ_TLS_REJECT_UNAUTHORIZED=true
|
|
RABBITMQ_SERVERNAME=
|
|
RABBITMQ_HEARTBEAT_SECONDS=10
|
|
RABBITMQ_RECONNECT_SECONDS=5
|
|
RABBITMQ_CONNECTION_TIMEOUT_MS=10000
|
|
NOTIFICATION_RPC_TIMEOUT_MS=3000
|
|
NOTIFICATION_RPC_RETRIES=1
|
|
NOTIFICATION_CIRCUIT_FAILURE_THRESHOLD=3
|
|
NOTIFICATION_CIRCUIT_RESET_MS=15000
|
|
NOTIFICATION_SERVICE_PORT=4001
|
|
NOTIFICATION_RMQ_PREFETCH=10
|
|
|
|
STORAGE_PROVIDER=local
|
|
MEDIA_ACCESS_MODE=direct
|
|
STORAGE_BASE_PATH=uploads
|
|
# In Docker/production with local storage, mount a persistent volume to /app/uploads
|
|
# or to the runtime path resolved from STORAGE_BASE_PATH.
|
|
# Leave empty for local storage unless you want a dedicated CDN/base URL.
|
|
STORAGE_PUBLIC_BASE_URL=
|
|
S3_BUCKET=
|
|
S3_REGION=auto
|
|
S3_ENDPOINT=
|
|
S3_ACCESS_KEY_ID=
|
|
S3_SECRET_ACCESS_KEY=
|
|
S3_FORCE_PATH_STYLE=false
|
|
# Optional: writes then deletes a tiny health object when GET /media/health runs.
|
|
# Keep false unless you explicitly want to verify S3 write permissions.
|
|
S3_HEALTH_WRITE_TEST_ENABLED=false
|
|
IMAGE_PROCESSING_ENABLED=true
|
|
IMAGE_PROCESSING_FFMPEG_PATH=ffmpeg
|
|
IMAGE_PROCESSING_LOW_WIDTH=360
|
|
IMAGE_PROCESSING_MEDIUM_WIDTH=720
|
|
IMAGE_PROCESSING_HIGH_WIDTH=1280
|
|
IMAGE_PROCESSING_QUALITY=78
|
|
VIDEO_PROCESSING_ENABLED=false
|
|
VIDEO_PROCESSING_FFMPEG_PATH=ffmpeg
|
|
VIDEO_PROCESSING_FFPROBE_PATH=ffprobe
|
|
VIDEO_PROCESSING_MAX_WIDTH=1280
|
|
VIDEO_PROCESSING_MAX_FPS=30
|
|
VIDEO_PROCESSING_CRF=28
|
|
VIDEO_PROCESSING_PRESET=veryfast
|
|
VIDEO_PROCESSING_AUDIO_BITRATE_KBPS=128
|
|
VIDEO_PROCESSING_GENERATE_THUMBNAILS=true
|
|
VIDEO_PROCESSING_GENERATE_HLS=true
|
|
VIDEO_PROCESSING_HLS_SEGMENT_DURATION_SECONDS=4
|
|
VIDEO_PROCESSING_THUMBNAIL_WIDTH=720
|
|
AUDIO_PROCESSING_ENABLED=false
|
|
AUDIO_WAVEFORM_PEAKS=100
|
|
|
|
GOOGLE_CLIENT_ID=your_google_client_id
|
|
GOOGLE_CLIENT_SECRET=your_google_client_secret
|
|
# Match this to the same reachable host/IP used in PUBLIC_BASE_URL.
|
|
GOOGLE_CALLBACK_URL=http://192.168.1.14:4000/api/v1/auth/google/callback
|
|
EMAIL_ENABLED=false
|
|
EMAIL_SMTP_HOST=smtp.gmail.com
|
|
EMAIL_SMTP_PORT=587
|
|
EMAIL_SMTP_SECURE=false
|
|
EMAIL_SMTP_USER=
|
|
EMAIL_SMTP_PASS=
|
|
EMAIL_FROM_NAME=Oudelaa
|
|
EMAIL_FROM_EMAIL=
|
|
# Enables POST /api/v1/media/ai/text-to-music.
|
|
# Uses Google Vertex AI publisher model endpoint, not GEMINI_API_KEY directly.
|
|
# Auth priority:
|
|
# 1. AI_MUSIC_API_KEY when set.
|
|
# 2. GOOGLE_APPLICATION_CREDENTIALS_JSON_BASE64 when set.
|
|
# 3. GOOGLE_APPLICATION_CREDENTIALS file path handled by google-auth-library.
|
|
AI_MUSIC_ENABLED=false
|
|
AI_MUSIC_API_KEY=
|
|
GOOGLE_APPLICATION_CREDENTIALS_JSON_BASE64=
|
|
AI_MUSIC_PROJECT_ID=accordev
|
|
AI_MUSIC_LOCATION=us-central1
|
|
AI_MUSIC_MODEL=lyria-002
|
|
|
|
|
|
SUPERADMIN_EMAIL=admin@oudelaa.com
|
|
SUPERADMIN_PASSWORD=SuperAdminStrongPass123!
|
|
# Required in production. Generate with bcrypt and leave SUPERADMIN_PASSWORD empty there.
|
|
SUPERADMIN_PASSWORD_HASH=
|
|
SUPERADMIN_ACCESS_SECRET=change_me_superadmin_access_secret
|
|
SUPERADMIN_ACCESS_EXPIRES_IN=15m
|
|
SUPERADMIN_REFRESH_SECRET=change_me_superadmin_refresh_secret
|
|
SUPERADMIN_REFRESH_EXPIRES_IN=30d
|
|
SUPERADMIN_TOTP_SECRET=
|