128 lines
5.3 KiB
Plaintext
128 lines
5.3 KiB
Plaintext
# =============================================================================
|
||
# Staging Environment - Template for api-gateway, worker, frontend
|
||
# =============================================================================
|
||
# Deploy script (deploy-staging.ps1) builds .env.staging by MERGING this file with
|
||
# ALL keys from your local backend/.env, worker/.env, frontend/.env. Real keys
|
||
# and secrets stay on your machine (SFTP upload only; no GitHub). Placeholders
|
||
# STAGING_* are replaced by the script; any variable in your local .env overrides
|
||
# or is added to the bundle. Replace STAGING_SERVER_IP / STAGING_DB_PASSWORD etc.
|
||
# in this example only if you do not have them in local .env.
|
||
# =============================================================================
|
||
|
||
NODE_ENV=development
|
||
API_PORT=4000
|
||
API_HOST=0.0.0.0
|
||
|
||
# Database (compose + api-gateway/worker)
|
||
DB_NAME=toolsplatform
|
||
DB_USER=postgres
|
||
DB_PASSWORD=STAGING_DB_PASSWORD_CHANGE_ME
|
||
# connection_limit and pool_timeout for production/staging (avoid Prisma defaults; tune per host)
|
||
DATABASE_URL=postgresql://postgres:STAGING_DB_PASSWORD_CHANGE_ME@postgres:5432/toolsplatform?schema=app&connection_limit=20&pool_timeout=10
|
||
|
||
# Redis / MinIO (service names in Docker)
|
||
REDIS_HOST=redis
|
||
REDIS_PORT=6379
|
||
MINIO_ENDPOINT=minio
|
||
MINIO_PORT=9000
|
||
MINIO_ACCESS_KEY=minioadmin
|
||
MINIO_SECRET_KEY=minioadmin
|
||
MINIO_BUCKET=uploads
|
||
MINIO_USE_SSL=false
|
||
|
||
# Keycloak (compose + api-gateway; PUBLIC_URL = browser-reachable)
|
||
KEYCLOAK_ADMIN=admin
|
||
KEYCLOAK_ADMIN_PASSWORD=STAGING_KEYCLOAK_PASSWORD_CHANGE_ME
|
||
KEYCLOAK_URL=http://keycloak:8080
|
||
# Use https://auth.getlinkzen.com after adding auth A record and running certbot
|
||
KEYCLOAK_PUBLIC_URL=https://auth.getlinkzen.com
|
||
KEYCLOAK_ISSUER_URI=https://auth.getlinkzen.com/realms/toolsplatform
|
||
KEYCLOAK_REALM=toolsplatform
|
||
KEYCLOAK_CLIENT_ID=api-gateway
|
||
KEYCLOAK_CLIENT_SECRET=
|
||
KEYCLOAK_ADMIN_CLIENT_ID=toolsplatform-admin
|
||
KEYCLOAK_ADMIN_CLIENT_SECRET=ZfhqZxgxMpRXvx0oFhzdGNd5rIyI0V5n
|
||
KEYCLOAK_USER_CLIENT_ID=toolsplatform-users
|
||
|
||
# Auth / security
|
||
JWT_ACCESS_TOKEN_TTL=15m
|
||
JWT_REFRESH_TOKEN_TTL=7d
|
||
JWT_REAUTH_WINDOW=5m
|
||
RATE_LIMIT_LOGIN_MAX=5
|
||
RATE_LIMIT_LOGIN_WINDOW=60000
|
||
RATE_LIMIT_REGISTER_MAX=3
|
||
RATE_LIMIT_REGISTER_WINDOW=60000
|
||
IP_HASH_SALT=staging-salt-change-for-production
|
||
RATE_LIMIT_GLOBAL_MAX=300
|
||
# Per-tier API rate limits (req/min); seed uses these, runtime reads from AppConfig
|
||
# RATE_LIMIT_GUEST=60
|
||
# RATE_LIMIT_FREE=120
|
||
# RATE_LIMIT_DAYPASS=180
|
||
# RATE_LIMIT_PRO=400
|
||
|
||
# Admin + frontend URLs
|
||
ADMIN_ROLE=platform-admin
|
||
ADMIN_DASHBOARD_ENABLED=true
|
||
FRONTEND_BASE_URL=https://app.getlinkzen.com
|
||
FRONTEND_PORT=3000
|
||
# Frontend uses NEXT_PUBLIC_API_BASE_URL in browser (lib/api.ts, config/constants.ts).
|
||
# MUST be the public domain (same origin). Traefik routes /api to the API.
|
||
# Do NOT set to http://SERVER_IP:4000 or API will receive wrong paths (POST /app, /api/route) and return 404.
|
||
NEXT_PUBLIC_API_BASE_URL=https://app.getlinkzen.com
|
||
NEXT_PUBLIC_API_URL=https://app.getlinkzen.com
|
||
NEXT_PUBLIC_KEYCLOAK_URL=https://auth.getlinkzen.com
|
||
# Next.js Server Actions: persistent encryption key (base64). REQUIRED for production/staging to avoid
|
||
# "Failed to find Server Action" and 504 after redeploys. Generate once, keep the same forever (all deploys):
|
||
# node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
||
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=
|
||
|
||
# Tier 2 (022) – fallback only; DB is source of truth. See docs/runtime-configuration-implementation.md §1.4
|
||
FEATURE_ADS_ENABLED=false
|
||
# Per-tier ads level: full | reduced | none (used when key missing in DB or for seed)
|
||
ADS_GUEST_LEVEL=full
|
||
ADS_FREE_LEVEL=reduced
|
||
ADS_DAYPASS_LEVEL=none
|
||
ADS_PRO_LEVEL=none
|
||
FEATURE_PAYMENTS_ENABLED=false
|
||
FEATURE_PREMIUM_TOOLS_ENABLED=true
|
||
FEATURE_REGISTRATION_ENABLED=true
|
||
RETENTION_GUEST_HOURS=1
|
||
RETENTION_FREE_HOURS=720
|
||
RETENTION_DAY_PASS_HOURS=720
|
||
RETENTION_PRO_HOURS=4320
|
||
ENABLE_SCHEDULED_CLEANUP=true
|
||
DAY_PASS_PRICE_USD=2.99
|
||
PRO_MONTHLY_PRICE_USD=9.99
|
||
PRO_YEARLY_PRICE_USD=99.99
|
||
|
||
# Processing services (Docker service names)
|
||
# Production (e.g. 8GB host): increase Stirling-PDF container memory in docker-compose.yml
|
||
# (e.g. deploy.resources.limits.memory: 1g or 2g) for PDF→EPUB and heavy conversions.
|
||
STIRLING_PDF_URL=http://stirling-pdf:8080
|
||
IMAGOR_URL=http://imagor:8000
|
||
REMBG_URL=http://rembg:7000
|
||
LANGUAGETOOL_URL=http://languagetool:8010
|
||
|
||
# Email (Resend) – deploy script uses RESEND_API_KEY from backend/.env if present; otherwise adds placeholder
|
||
RESEND_API_KEY=re_dummy_staging_placeholder
|
||
# Always enable email on staging (script ensures this)
|
||
EMAIL_ENABLED=true
|
||
|
||
# Paddle (sandbox for staging) – webhook URL: https://app.getlinkzen.com/api/v1/webhooks/paddle
|
||
FEATURE_PADDLE_ENABLED=true
|
||
PADDLE_VENDOR_ID=47301
|
||
PADDLE_API_KEY=pdl_sdbx_apikey_01kgjbr76ej9557epyqhkqctb2_aCTHTA3gSVCms9BEzVMCbt_Aef
|
||
PADDLE_WEBHOOK_SECRET=ntfset_01kgjc7kwad46116eaba5hra6d
|
||
PADDLE_ENVIRONMENT=sandbox
|
||
NEXT_PUBLIC_PADDLE_ENVIRONMENT=sandbox
|
||
NEXT_PUBLIC_PADDLE_CLIENT_TOKEN=test_a6db5d833f9caf2762d3266edf3
|
||
NEXT_PUBLIC_PADDLE_PRICE_ID_DAY_PASS=pri_01kgjcdd3jbw444yd2v48cswj5
|
||
NEXT_PUBLIC_PADDLE_PRICE_ID_PRO_MONTHLY=pri_01kgjcfhbshf3yv1s7k0qsx42q
|
||
NEXT_PUBLIC_PADDLE_PRICE_ID_PRO_YEARLY=pri_01kgjcjg9rh0jkymqgjndk6tb9
|
||
|
||
# Worker
|
||
WORKER_CONCURRENCY=3
|
||
|
||
# Phase 10 monitoring (Grafana admin password; used when docker-compose.monitoring.yml is used)
|
||
GRAFANA_PASSWORD=staging-grafana-change-me
|