Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 75 additions & 110 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,154 +1,119 @@
# =============================================================================
# Trading Room SaaS - Environment Variables
# Trading Room Environment Variables
# =============================================================================
# Copy this file to .env and fill in the values
# =============================================================================
# NOTE: These are DEVELOPMENT defaults. For production deployment,
# see DEPLOYMENT_GUIDE.md for proper production configuration.
# Copy to `.env` and fill in the values. See SETUP_KEYS.md for a step-by-step
# walkthrough of where every value comes from, and DEPLOYMENT_GUIDE.md for prod.
#
# Legend: 🔐 generate yourself (openssl) 🧩 from a provider 🖥️ from a server
# =============================================================================

# Application
APP_ENV=development
APP_DEBUG=true
APP_URL=http://localhost:8000
APP_KEY=

# Node Environment
# --- Runtime ----------------------------------------------------------------
NODE_ENV=development
RUST_LOG=info,api=debug
APP_URL=http://localhost:5173 # public base URL of the frontend

# =============================================================================
# Database Configuration (Neon Serverless PostgreSQL)
# =============================================================================
# Sign up at: https://neon.tech
# Neon provides serverless Postgres with branching, scale-to-zero, and auto-scaling
#
# Get your connection string from Neon Console → Connection Details
# Rust API (backend-rs)
# =============================================================================
API_HOST=0.0.0.0
API_PORT=8080

# Postgres connection string (🧩 Neon, or the local compose Postgres).
# Local compose example: postgresql://postgres:postgres@localhost:5432/tradingroom
DATABASE_URL=postgresql://user:password@ep-xxx.region.aws.neon.tech/neondb?sslmode=require
DB_HOST=ep-xxx.region.aws.neon.tech
DB_NAME=neondb
DB_USER=your-neon-user
DB_PASSWORD=your-neon-password
DB_PORT=5432
DB_SSL=true

# Comma-separated origins allowed by the API (frontend + dev ports).
CORS_ORIGINS=http://localhost:5173,http://localhost:3000

# How the API reaches the signaling control-plane.
SIGNALING_URL=http://localhost:3000
# 🔐 Shared secret the API presents to signaling. MUST equal signaling's
# SIGNALING_SERVER_SECRET below. -> openssl rand -hex 32
SIGNALING_SECRET=

# 🔐 JWT signing secret (auth + room tokens). -> openssl rand -hex 32
JWT_SECRET=

# =============================================================================
# Stripe Configuration (use TEST keys for development)
# Stripe (🧩 stripe.com — use TEST keys for development)
# =============================================================================
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

# Stripe Price IDs
STRIPE_PRICE_STARTER_MONTHLY=price_xxx
STRIPE_PRICE_PROFESSIONAL_MONTHLY=price_xxx
STRIPE_PRICE_BUSINESS_MONTHLY=price_xxx
STRIPE_KEY=pk_test_xxx # publishable key (frontend)
# NOTE: per-plan price IDs are NOT env vars — seed them into the `plans` table
# (see SUBSCRIPTIONS_AND_TIERS.md §2.3).

# =============================================================================
# Cloudflare R2 Storage
# Cloudflare R2 (🧩 object storage, S3-compatible)
# =============================================================================
R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
R2_BUCKET=tradingroom-files
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET=tradingroom-files
R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
R2_PUBLIC_URL=https://files.tradingroom.io
R2_REGION=auto

# =============================================================================
# Redis Configuration
# Frontend (SvelteKit BFF)
# =============================================================================
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=tradingroom_redis
REDIS_URL=redis://127.0.0.1:6379
API_URL=http://localhost:8080 # server-side → Rust API
PUBLIC_SIGNALING_URL=ws://localhost:3000/ws

# =============================================================================
# Signaling Server
# Signaling server (Node)
# =============================================================================
SIGNALING_URL=http://localhost:3000
SIGNALING_WS_URL=ws://localhost:3000/ws
SIGNALING_SECRET=your-signaling-secret
SIGNALING_PORT=3000
PORT=3000 # signaling listen port (container)
LOG_LEVEL=debug
# 🔐 Control-plane bearer protecting signaling /api/* — set EQUAL to the API's
# SIGNALING_SECRET above, and reuse as the SFU's secret below.
SIGNALING_SERVER_SECRET=
# Split DB vars used by the signaling service (point at the same DB as DATABASE_URL).
DB_HOST=ep-xxx.region.aws.neon.tech
DB_NAME=neondb
DB_USER=your-neon-user
DB_PASSWORD=your-neon-password
DB_PORT=5432
DB_SSL=true

# =============================================================================
# SFU Configuration
# Redis (self-hosted in compose, or 🧩 Upstash/Redis Cloud)
# =============================================================================
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
# 🔐 openssl rand -hex 16
REDIS_PASSWORD=
REDIS_URL=redis://127.0.0.1:6379

# =============================================================================
# SFU (mediasoup) — runs with host networking; see docs/MEDIA_INFRASTRUCTURE.md
# =============================================================================
SFU_NODE_ID=sfu-1
# How signaling reaches the SFU control-plane (host:port). The SFU runs with
# host networking, so in production set this to the SFU box's reachable address
# (e.g. sfu1.<domain>:4000), not the bridge service name.
# How signaling reaches the SFU control-plane. In prod: sfu1.<domain>:4000
SFU_NODES=localhost:4000
# The SFU host's PUBLIC IPv4 — wired into the SFU as MEDIASOUP_ANNOUNCED_IP.
# Clients connect here for WebRTC media; must be a real public IP in production.
# 🖥️ The SFU host's PUBLIC IPv4 (→ MEDIASOUP_ANNOUNCED_IP). Clients connect here
# for WebRTC media. Must be a real public IP in production.
SFU_ANNOUNCED_IP=127.0.0.1
SFU_PORT=4000

# Mediasoup RTC media port range (UDP primary + TCP fallback). The SFU service
# in docker-compose pins MEDIASOUP_RTC_MIN_PORT/MAX_PORT to this window — open it
# in the firewall on the SFU host.
# 🔐 SFU control-plane secret — set EQUAL to SIGNALING_SERVER_SECRET.
SFU_SECRET=
# Mediasoup RTC media port range (UDP primary + TCP fallback) — open in firewall.
RTC_MIN_PORT=40000
RTC_MAX_PORT=49999

# =============================================================================
# TURN Server Configuration
# TURN / STUN (coturn — self-hosted in compose)
# =============================================================================
TURN_SERVER_URL=turn:localhost:3478
STUN_SERVER_URL=stun:localhost:3478
TURN_SERVER_USERNAME=tradingroom
TURN_SERVER_CREDENTIAL=your-turn-password
STUN_SERVER_URL=stun:localhost:3478

# =============================================================================
# CORS Configuration
# =============================================================================
CORS_ORIGINS=http://localhost:5173,http://localhost:3000,http://localhost:8000

# =============================================================================
# JWT Configuration
# =============================================================================
JWT_SECRET=your-jwt-secret
JWT_EXPIRY=86400

# =============================================================================
# Frontend URLs
# =============================================================================
FRONTEND_URL=http://localhost:5173
API_URL=http://localhost:8000

# =============================================================================
# Logging & Monitoring
# =============================================================================
LOG_LEVEL=debug
SENTRY_DSN=
SENTRY_ENVIRONMENT=development

# =============================================================================
# Email Configuration (Laravel)
# =============================================================================
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@localhost
MAIL_FROM_NAME="Trading Room (Dev)"

# =============================================================================
# Queue Configuration (Laravel)
# =============================================================================
QUEUE_CONNECTION=redis
HORIZON_PREFIX=tradingroom_horizon:

# =============================================================================
# Rate Limiting
# =============================================================================
RATE_LIMIT_API=100
RATE_LIMIT_AUTH=5
RATE_LIMIT_WEBSOCKET=10
# 🔐 coturn static-auth-secret (time-limited REST credentials). openssl rand -hex 32
TURN_AUTH_SECRET=
# 🖥️ TURN host's PUBLIC IPv4 (coturn external-ip).
TURN_EXTERNAL_IP=127.0.0.1

# =============================================================================
# Feature Flags
# Observability (⚪ optional)
# =============================================================================
FEATURE_RECORDING=true
FEATURE_SCREEN_SHARE=true
FEATURE_CHAT=true
FEATURE_ALERTS=true
# OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318
# SENTRY_DSN=
Loading