Environment Variables Configuration
Complete guide to configuring OpenLift service environment variables, including required settings, conditional dependencies, and production recommendations.
Overview
OpenLift uses environment variables for all configuration. Copy default.env to .env and update values for your deployment.
cp default.env .env
# Edit .env with your actual configuration
Required Environment Variables
Core Application Settings
| Variable | Required | Default | Description |
|---|
NODE_ENV | Yes | local | Application environment (local, development, staging, production) |
PORT | No | 8000 | HTTP server port |
HOST | No | 0.0.0.0 | HTTP server bind address |
Database Configuration
| Variable | Required | Default | Description |
|---|
MONGO_DATABASE_URL | Yes | None | MongoDB connection string with authentication |
Example MongoDB URLs:
# Local MongoDB
MONGO_DATABASE_URL=mongodb://username:password@localhost:27017/openfit-dev?authSource=admin
# MongoDB Atlas
MONGO_DATABASE_URL=mongodb+srv://username:password@cluster.mongodb.net/openfit?retryWrites=true&w=majority
# MongoDB with replica set
MONGO_DATABASE_URL=mongodb://user:pass@host1:27017,host2:27017,host3:27017/openfit?replicaSet=myReplicaSet&authSource=admin
Security Configuration
| Variable | Required | Default | Description |
|---|
COOKIE_SECRET | Production | None | Secret for signing cookies (32+ characters) |
JWT_PRIVATE_KEY_PATH | Yes | ./private.pem | Path to RSA private key for JWT signing |
JWT_PUBLIC_KEY_PATH | Yes | ./public.pem | Path to RSA public key for JWT verification |
JWT_ACCESS_TOKEN_EXPIRES_IN | No | 15m | JWT token expiration (15 minutes recommended) |
JWT_ISSUER | No | open-fit-dev | JWT issuer identifier |
JWT_AUDIENCE | No | open-fit-users-dev | JWT audience identifier |
CORS_ORIGIN | No | ^$ | CORS origin pattern (regex) |
Generate JWT Keys:
# Generate RSA private key
ssh-keygen -t rsa -b 4096 -m PEM -f private.pem
# Extract public key
ssh-keygen -f private.pem -e -m PEM > public.pem
Security Requirements by Environment:
- Development:
COOKIE_SECRET optional (warning shown)
- Production:
COOKIE_SECRET mandatory (application fails without it)
Object Storage Configuration
OpenLift supports two object storage providers: Cloudflare R2 (recommended) or MinIO (self-hosted).
Provider Selection
| Variable | Required | Default | Options | Description |
|---|
OBJECT_STORAGE_PROVIDER | Yes | R2 | R2, MINIO | Object storage provider |
Cloudflare R2 Configuration
Required when OBJECT_STORAGE_PROVIDER=R2:
| Variable | Required | Default | Description |
|---|
R2_ACCOUNT_ID | Yes | None | Cloudflare R2 account ID |
R2_ACCESS_KEY_ID | Yes | None | R2 API access key |
R2_SECRET_ACCESS_KEY | Yes | None | R2 API secret key |
R2_USER_ASSETS_BUCKET_NAME | Yes | None | Bucket for user-uploaded content |
R2_EXERCISE_ASSETS_BUCKET_NAME | Yes | None | Bucket for exercise images/videos |
R2_APP_ASSETS_BUCKET_NAME | No | None | Bucket for application assets (optional) |
R2_ENDPOINT_OVERRIDE | No | None | Custom R2 endpoint (optional) |
Example R2 Configuration:
OBJECT_STORAGE_PROVIDER=R2
R2_ACCOUNT_ID=a1b2c3d4e5f6789012345678
R2_ACCESS_KEY_ID=a1b2c3d4e5f67890123456789abc123456789abc
R2_SECRET_ACCESS_KEY=def123456789abc123456789def123456789abc123456789def1234567890
R2_USER_ASSETS_BUCKET_NAME=openfit-prod-user-assets
R2_EXERCISE_ASSETS_BUCKET_NAME=openfit-prod-exercise-assets
R2_APP_ASSETS_BUCKET_NAME=openfit-prod-app-assets
MinIO Configuration
Required when OBJECT_STORAGE_PROVIDER=MINIO:
| Variable | Required | Default | Description |
|---|
MINIO_ENDPOINT | Yes | None | MinIO server hostname/IP |
MINIO_PORT | No | 9000 | MinIO server port |
MINIO_ACCESS_KEY | Yes | None | MinIO access key |
MINIO_SECRET_KEY | Yes | None | MinIO secret key |
MINIO_USE_SSL | No | false | Enable SSL/TLS connection |
MINIO_USER_ASSETS_BUCKET_NAME | Yes | None | Bucket for user-uploaded content |
MINIO_EXERCISE_ASSETS_BUCKET_NAME | Yes | None | Bucket for exercise images/videos |
MINIO_APP_ASSETS_BUCKET_NAME | No | None | Bucket for application assets (optional) |
Example MinIO Configuration:
OBJECT_STORAGE_PROVIDER=MINIO
MINIO_ENDPOINT=minio.yourdomain.com
MINIO_PORT=9000
MINIO_ACCESS_KEY=your-minio-access-key
MINIO_SECRET_KEY=your-minio-secret-key-32chars-min
MINIO_USE_SSL=true
MINIO_USER_ASSETS_BUCKET_NAME=openfit-user-assets
MINIO_EXERCISE_ASSETS_BUCKET_NAME=openfit-exercise-assets
Object Storage General Settings
| Variable | Required | Default | Description |
|---|
SIGNED_URL_DEFAULT_EXPIRATION_SECONDS | No | 604800 | Signed URL expiration (7 days) |
MAX_SERVER_UPLOAD_FILE_SIZE_BYTES | No | 10485760 | Max upload size (10MB) |
ALLOWED_SERVER_UPLOAD_MIME_TYPES | No | See below | Comma-separated allowed MIME types |
Default Allowed MIME Types:
ALLOWED_SERVER_UPLOAD_MIME_TYPES=image/jpeg,image/png,image/gif,image/webp,image/heic,image/heif
Asset Retention Configuration
Configure automatic cleanup of old user assets:
| Variable | Required | Default | Description |
|---|
PROGRESS_PHOTOS_RETENTION_COUNT | No | 10 | Keep last N progress photos per type |
PROGRESS_PHOTOS_AUTO_CLEANUP | No | true | Auto-archive old progress photos |
PROFILE_PICTURES_RETENTION_COUNT | No | 5 | Keep last N profile pictures |
PROFILE_PICTURES_AUTO_CLEANUP | No | true | Auto-archive old profile pictures |
WORKOUT_TEMPLATE_IMAGES_RETENTION_COUNT | No | 10 | Keep last N workout template images |
WORKOUT_TEMPLATE_IMAGES_AUTO_CLEANUP | No | true | Auto-archive old template images |
WORKOUT_PROGRAM_IMAGES_RETENTION_COUNT | No | 10 | Keep last N program images |
WORKOUT_PROGRAM_IMAGES_AUTO_CLEANUP | No | true | Auto-archive old program images |
APP_IMAGES_RETENTION_COUNT | No | 20 | Keep last N app images per category |
APP_IMAGES_AUTO_CLEANUP | No | true | Auto-archive old app images |
Enterprise Observability Configuration
Advanced logging, metrics, and monitoring for production deployments.
Core Observability Features
| Variable | Required | Default | Description |
|---|
OBSERVABILITY_ENABLED | No | false | Enable enterprise observability system |
METRICS_ENABLED | No | true | Enable metrics collection |
LOGS_ENABLED | No | true | Enable logging system |
Advanced Feature Flags
| Variable | Required | Default | Description |
|---|
ENABLE_LOKI_SHIPPING | No | true | Ship logs to Grafana Loki |
ENABLE_LOCAL_FALLBACK | No | true | Local file fallback when Loki unavailable |
ENABLE_CIRCUIT_BREAKER | No | true | Circuit breaker for logging reliability |
ENABLE_CORRELATION_ID | No | true | Request correlation tracking |
ENABLE_DATA_SANITIZATION | No | true | PII sanitization (always enabled in production) |
ENABLE_COMPRESSION | No | true | Compress log payloads |
ENABLE_ADAPTIVE_BATCHING | No | true | Adaptive batch sizing |
ENABLE_PERFORMANCE_MONITORING | No | true | Performance metrics collection |
Grafana Cloud Configuration
Required when observability is enabled in production:
| Variable | Required | Default | Description |
|---|
LOKI_ENDPOINT | Prod | None | Grafana Loki push endpoint URL |
LOKI_USERNAME | Prod | None | Grafana Loki username |
LOKI_PASSWORD | Prod | None | Grafana Loki API key |
PROMETHEUS_ENDPOINT | Prod | None | Grafana Prometheus push endpoint URL |
PROMETHEUS_USERNAME | Prod | None | Grafana Prometheus username |
PROMETHEUS_PASSWORD | Prod | None | Grafana Prometheus API key |
Example Grafana Cloud Configuration:
OBSERVABILITY_ENABLED=true
LOKI_ENDPOINT=https://logs-prod-012.grafana.net/loki/api/v1/push
LOKI_USERNAME=123456
LOKI_PASSWORD=glc_eyJrIjoiabcd1234567890...
PROMETHEUS_ENDPOINT=https://prometheus-prod-12-abc.grafana.net/api/prom/push
PROMETHEUS_USERNAME=123456
PROMETHEUS_PASSWORD=glc_eyJrIjoixyz9876543210...
| Variable | Required | Default | Description |
|---|
LOKI_BATCH_SIZE | No | 1000 | Log entries per batch |
LOKI_BATCH_INTERVAL | No | 5000 | Batch flush interval (ms) |
LOKI_MAX_BATCH_SIZE | No | 5000 | Maximum batch size |
LOKI_MIN_BATCH_SIZE | No | 100 | Minimum batch size |
Connection Configuration
| Variable | Required | Default | Description |
|---|
LOKI_CONNECTION_TIMEOUT | No | 30000 | Connection timeout (ms) |
LOKI_REQUEST_TIMEOUT | No | 60000 | Request timeout (ms) |
LOKI_KEEPALIVE_TIMEOUT | No | 120000 | Keep-alive timeout (ms) |
Retry Configuration
| Variable | Required | Default | Description |
|---|
LOKI_RETRY_ATTEMPTS | No | 3 | Maximum retry attempts |
LOKI_RETRY_DELAY | No | 1000 | Initial retry delay (ms) |
LOKI_RETRY_BACKOFF_FACTOR | No | 2.0 | Exponential backoff factor |
LOKI_RETRY_MAX_DELAY | No | 30000 | Maximum retry delay (ms) |
Circuit Breaker Configuration
| Variable | Required | Default | Description |
|---|
CIRCUIT_BREAKER_ERROR_THRESHOLD | No | 50 | Error percentage threshold (1-100) |
CIRCUIT_BREAKER_MIN_REQUESTS | No | 20 | Minimum requests before triggering |
CIRCUIT_BREAKER_TIMEOUT | No | 60000 | Circuit breaker timeout (ms) |
CIRCUIT_BREAKER_RESET_TIMEOUT | No | 120000 | Circuit breaker reset timeout (ms) |
Buffer Management
| Variable | Required | Default | Description |
|---|
LOG_BUFFER_SIZE | No | 100000 | Log buffer size (entries) |
LOG_BUFFER_MEMORY_LIMIT | No | 50MB | Memory limit for log buffer |
LOG_BUFFER_HIGH_WATER_MARK | No | 80 | High water mark percentage |
LOG_BUFFER_LOW_WATER_MARK | No | 60 | Low water mark percentage |
Local Fallback Configuration
| Variable | Required | Default | Description |
|---|
FALLBACK_LOG_DIRECTORY | No | ./logs | Local fallback log directory |
FALLBACK_MAX_FILE_SIZE | No | 100MB | Maximum log file size |
FALLBACK_MAX_FILES | No | 5 | Maximum number of log files |
FALLBACK_COMPRESS_FILES | No | true | Compress rotated log files |
Service Identification
| Variable | Required | Default | Description |
|---|
SERVICE_NAME | No | openlift-service | Service name for logs/metrics |
SERVICE_VERSION | No | 1.0.0 | Service version |
DEPLOYMENT_ENVIRONMENT | No | development | Deployment environment label |
CLUSTER_NAME | No | local-dev | Cluster/deployment identifier |
INSTANCE_ID | No | Auto-generated | Unique instance identifier |
Data Sanitization
| Variable | Required | Default | Description |
|---|
PII_DETECTION_ENABLED | No | true | Enable PII detection (always on in prod) |
REDACT_SENSITIVE_FIELDS | No | true | Redact sensitive fields (always on in prod) |
SENSITIVE_FIELD_PATTERNS | No | See below | Comma-separated sensitive field patterns |
Default Sensitive Field Patterns:
SENSITIVE_FIELD_PATTERNS=email,password,token,secret,key,authorization
Production automatically adds: user_id,session_id,correlation_id,request_id,ip_address,user_agent
| Variable | Required | Default | Description |
|---|
ADAPTIVE_BATCH_MIN_LATENCY | No | 100 | Minimum target latency (ms) |
ADAPTIVE_BATCH_MAX_LATENCY | No | 10000 | Maximum target latency (ms) |
ADAPTIVE_BATCH_TARGET_LATENCY | No | 2000 | Target latency for optimization (ms) |
ADAPTIVE_BATCH_ADJUSTMENT_FACTOR | No | 0.1 | Batch size adjustment factor |
Optional Configuration Variables
| Variable | Required | Default | Description |
|---|
ENABLE_GRAPHQL_PLAYGROUND | No | true | Enable GraphQL Playground UI |
ENABLE_METRICS_ENDPOINT | No | true | Expose metrics endpoint |
ENABLE_DEBUG_LOGGING | No | true | Enable debug-level logging |
ENABLE_GRAPHQL_ERROR_LOGGING | No | true | Log GraphQL errors |
Rate Limiting
| Variable | Required | Default | Description |
|---|
RATE_LIMIT_MAX_REQUESTS | No | Production: 100 Dev: 500000000 | Requests per minute limit |
Logging
| Variable | Required | Default | Description |
|---|
LOG_LEVEL | No | info | Log level (trace, debug, info, warn, error, fatal) |
Legacy/Compatibility
| Variable | Required | Default | Description |
|---|
IMAGE_STORAGE_TYPE | No | local | Legacy image storage type |
LOG_BATCH_SIZE | No | 1000 | Legacy log batch size |
LOG_FLUSH_INTERVAL | No | 5000 | Legacy log flush interval |
METRICS_PUSH_INTERVAL | No | 15000 | Legacy metrics push interval |
ENVIRONMENT | No | development | Legacy environment variable |
Configuration Logic & Dependencies
Object Storage Provider Logic
if OBJECT_STORAGE_PROVIDER=R2 then
# R2 variables are required
R2_ACCOUNT_ID=required
R2_ACCESS_KEY_ID=required
R2_SECRET_ACCESS_KEY=required
R2_USER_ASSETS_BUCKET_NAME=required
R2_EXERCISE_ASSETS_BUCKET_NAME=required
# R2_APP_ASSETS_BUCKET_NAME=optional
# R2_ENDPOINT_OVERRIDE=optional
# MinIO variables are ignored
MINIO_*=ignored
elif OBJECT_STORAGE_PROVIDER=MINIO then
# MinIO variables are required
MINIO_ENDPOINT=required
MINIO_ACCESS_KEY=required
MINIO_SECRET_KEY=required
MINIO_USER_ASSETS_BUCKET_NAME=required
MINIO_EXERCISE_ASSETS_BUCKET_NAME=required
# MINIO_PORT=optional (default: 9000)
# MINIO_USE_SSL=optional (default: false)
# MINIO_APP_ASSETS_BUCKET_NAME=optional
# R2 variables are ignored
R2_*=ignored
Environment-Based Security Requirements
if NODE_ENV=production then
COOKIE_SECRET=required (application fails without it)
if OBSERVABILITY_ENABLED=true then
LOKI_ENDPOINT=required
LOKI_USERNAME=required
LOKI_PASSWORD=required
PROMETHEUS_ENDPOINT=required
PROMETHEUS_USERNAME=required
PROMETHEUS_PASSWORD=required
fi
# Privacy settings always enabled regardless of flags
PII_DETECTION_ENABLED=true (forced)
REDACT_SENSITIVE_FIELDS=true (forced)
else
COOKIE_SECRET=optional (warning shown if missing)
fi
Observability Batch Configuration Validation
# These must maintain proper relationships
LOKI_MIN_BATCH_SIZE ≤ LOKI_BATCH_SIZE ≤ LOKI_MAX_BATCH_SIZE
# Buffer water marks must be sensible
10 ≤ LOG_BUFFER_LOW_WATER_MARK < LOG_BUFFER_HIGH_WATER_MARK ≤ 95
# Timeouts must be ordered correctly
LOKI_CONNECTION_TIMEOUT < LOKI_REQUEST_TIMEOUT
# Retry configuration must be reasonable
LOKI_RETRY_DELAY ≤ LOKI_RETRY_MAX_DELAY
LOKI_RETRY_ATTEMPTS ≤ 10
# Circuit breaker thresholds
1 ≤ CIRCUIT_BREAKER_ERROR_THRESHOLD ≤ 100
# Adaptive batching latency ordering
ADAPTIVE_BATCH_MIN_LATENCY < ADAPTIVE_BATCH_MAX_LATENCY
Environment-Specific Configuration Examples
Development (.env.development)
NODE_ENV=development
PORT=8000
MONGO_DATABASE_URL=mongodb://localhost:27017/openfit-dev
COOKIE_SECRET=dev-cookie-secret-minimum-32-characters
# Development JWT keys
JWT_PRIVATE_KEY_PATH=./dev-private.pem
JWT_PUBLIC_KEY_PATH=./dev-public.pem
CORS_ORIGIN=^http://localhost
# Local MinIO for development
OBJECT_STORAGE_PROVIDER=MINIO
MINIO_ENDPOINT=localhost
MINIO_PORT=9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_USE_SSL=false
MINIO_USER_ASSETS_BUCKET_NAME=dev-user-assets
MINIO_EXERCISE_ASSETS_BUCKET_NAME=dev-exercise-assets
# Development tools
ENABLE_GRAPHQL_PLAYGROUND=true
ENABLE_DEBUG_LOGGING=true
LOG_LEVEL=debug
# Relaxed rate limiting
RATE_LIMIT_MAX_REQUESTS=500000000
# Simple observability
OBSERVABILITY_ENABLED=false
ENABLE_LOCAL_FALLBACK=true
Production (.env.production)
NODE_ENV=production
PORT=8000
MONGO_DATABASE_URL=mongodb+srv://user:pass@cluster.mongodb.net/openfit-prod?retryWrites=true&w=majority
COOKIE_SECRET=super-secure-production-cookie-secret-64-characters-minimum
# Production JWT keys (secure file permissions)
JWT_PRIVATE_KEY_PATH=/app/secrets/jwt-private.pem
JWT_PUBLIC_KEY_PATH=/app/secrets/jwt-public.pem
CORS_ORIGIN=^https://yourdomain\.com$
# Cloudflare R2 for production
OBJECT_STORAGE_PROVIDER=R2
R2_ACCOUNT_ID=your-production-account-id
R2_ACCESS_KEY_ID=your-production-access-key
R2_SECRET_ACCESS_KEY=your-production-secret-key
R2_USER_ASSETS_BUCKET_NAME=openfit-prod-user-assets
R2_EXERCISE_ASSETS_BUCKET_NAME=openfit-prod-exercise-assets
R2_APP_ASSETS_BUCKET_NAME=openfit-prod-app-assets
# Production security
ENABLE_GRAPHQL_PLAYGROUND=false
ENABLE_DEBUG_LOGGING=false
LOG_LEVEL=warn
RATE_LIMIT_MAX_REQUESTS=100
# Enterprise observability
OBSERVABILITY_ENABLED=true
LOKI_ENDPOINT=https://logs-prod-012.grafana.net/loki/api/v1/push
LOKI_USERNAME=123456
LOKI_PASSWORD=your-loki-api-key
PROMETHEUS_ENDPOINT=https://prometheus-prod-12-abc.grafana.net/api/prom/push
PROMETHEUS_USERNAME=123456
PROMETHEUS_PASSWORD=your-prometheus-api-key
# Production performance tuning
LOKI_BATCH_SIZE=1000
LOKI_BATCH_INTERVAL=5000
ENABLE_CIRCUIT_BREAKER=true
ENABLE_DATA_SANITIZATION=true
ENABLE_ADAPTIVE_BATCHING=true
# Service identification
SERVICE_NAME=openlift-service
SERVICE_VERSION=1.2.0
DEPLOYMENT_ENVIRONMENT=production
CLUSTER_NAME=prod-cluster-us-east
Configuration Validation
The service validates configuration on startup and will fail with clear error messages for:
- Missing Required Variables: Database URL, JWT keys, object storage credentials
- Invalid Combinations: Conflicting object storage provider settings
- Production Security: Missing cookie secret in production
- Observability Logic: Invalid batch sizes, timeout ordering, threshold ranges
- File Permissions: JWT key files not readable
- Network Configuration: Invalid MongoDB connection strings
Health Monitoring Endpoints
When observability is enabled, these endpoints are available:
- Health Check:
GET /health/logging - Service health status
- Metrics:
GET /metrics/logging - Performance metrics
- Manual Flush:
POST /admin/logging/flush - Force log flush
Best Practices
Security
- Use strong, unique secrets (32+ characters for
COOKIE_SECRET)
- Secure JWT key file permissions (600 or 400)
- Enable HTTPS in production
- Use proper CORS origin patterns
- Never commit secrets to version control
- Use appropriate batch sizes for your log volume
- Enable compression for high-volume deployments
- Configure circuit breakers for reliability
- Monitor buffer usage and adjust water marks
- Use R2 for better global performance
Reliability
- Always enable local fallback for logging
- Configure appropriate retry policies
- Set reasonable timeout values
- Use correlation IDs for request tracing
- Enable health checks in load balancers
Privacy
- Data sanitization is always enabled in production
- Configure additional sensitive field patterns as needed
- Review log retention policies
- Use secure MongoDB connections with authentication
- Regularly rotate access keys and secrets
For additional configuration help, see the Installation Overview or check the default.env file in the service repository.