Overview
Open Wearables is configured entirely through environment variables defined in backend/config/.env. This guide documents all available configuration options with their purposes, default values, and security considerations.
Configuration File
The backend loads configuration from backend/config/.env:
cp backend/config/.env.example backend/config/.env
Never commit .env files to version control. The .env.example file provides a template with placeholder values.
Core Settings
Environment
Type: local | test | staging | production
Description: Determines the runtime environment. Affects logging verbosity, error reporting, and behavior of certain features.
local - Development with debug logging
test - Automated testing environment
staging - Pre-production testing
production - Production deployment with optimized settings
CORS Configuration
CORS_ORIGINS = ["http://localhost:3000" ]
Type: JSON array of URLs
Description: Allowed origins for Cross-Origin Resource Sharing (CORS). Must include your frontend URL.
CORS_ORIGINS = ["http://localhost:3000" ]
Never use ["*"] in production as it allows requests from any origin, creating a security vulnerability.
Server Host
SERVER_HOST = "https://api.example.com"
Type: URL
Description: Public URL where your API is accessible. Used for generating OAuth callback URLs and email links.
Authentication
Secret Key
SECRET_KEY = your-secret-key-here
Type: String (minimum 32 characters recommended)
Description: Used for signing JWT tokens and securing sessions. Must be kept secret and unique per deployment.
Generate a secure key:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
Critical Security Requirement:
Generate a new secret key for each environment
Never reuse keys between development and production
Never commit the secret key to version control
Changing this key invalidates all existing user sessions
Token Configuration
# Not typically needed - defaults are secure
# ALGORITHM="HS256"
# ACCESS_TOKEN_EXPIRE_MINUTES=60
# TOKEN_LIFETIME=3600
These settings are managed automatically by the application. Only modify if you have specific security requirements.
Database Configuration
PostgreSQL Settings
DB_HOST = db
DB_PORT = 5432
DB_NAME = open-wearables
DB_USER = open-wearables
DB_PASSWORD = open-wearables
Docker Compose
External Database
# When using docker-compose.yml services
DB_HOST = db
DB_PORT = 5432
DB_NAME = open-wearables
DB_USER = open-wearables
DB_PASSWORD = open-wearables
Connection string format:
postgresql+psycopg://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}
Production databases must use strong passwords. Default credentials are only for local development.
See Database Setup for migration and backup strategies.
Redis Configuration
Connection Settings
REDIS_HOST = redis
REDIS_PORT = 6379
REDIS_DB = 0
Description: Redis is used as a message broker for Celery tasks and for caching sleep session state.
Redis Authentication (Production)
# Uncomment and set for production
# REDIS_PASSWORD=your-secure-password
# REDIS_USERNAME=default # For Redis 6.0+ ACL
REDIS_HOST = redis
REDIS_PORT = 6379
REDIS_DB = 0
# No authentication in development
Always enable Redis authentication in production environments. An open Redis instance is a critical security vulnerability.
Redis TTL Settings
# REDIS_SLEEP_TTL_SECONDS=86400 # 24 hours (default)
# SLEEP_END_GAP_MINUTES=120 # 2 hours (default)
Description:
REDIS_SLEEP_TTL_SECONDS - How long to keep sleep session state in Redis
SLEEP_END_GAP_MINUTES - Time gap between sleep phases to conclude sleep session ended
Email Configuration (Resend)
RESEND_API_KEY = your-resend-api-key
EMAIL_FROM_ADDRESS = "[email protected] "
EMAIL_FROM_NAME = "Open Wearables"
FRONTEND_URL = http://localhost:3000
Description: Email service for user invitations, password resets, and notifications.
Getting started with Resend:
Add your domain
Add and verify your sending domain in the Resend dashboard
Generate API key
Create an API key and copy it to RESEND_API_KEY
Configure sender
Update EMAIL_FROM_ADDRESS to use your verified domain
Configuration options:
Variable Description Example RESEND_API_KEYAPI key from Resend dashboard re_123abc...EMAIL_FROM_ADDRESSSender email address [email protected] EMAIL_FROM_NAMESender display name Open WearablesFRONTEND_URLFrontend base URL for email links https://app.example.comINVITATION_EXPIRE_DAYSDays until invitation expires (default: 7) 7EMAIL_MAX_RETRIESMax retry attempts for failed emails (default: 5) 5
Development tip: Use Resend’s test mode during development to avoid sending real emails. All test emails appear in your Resend dashboard.
Admin Account
Description: Default admin account created automatically on first startup if no developer account exists.
Change the default admin password immediately in production. The default credentials are publicly known.
Account creation behavior:
Checked on every application startup
Only created if no admin accounts exist in the database
Email and password can be changed via environment variables
Recommended: Create admin via API and remove these variables in production
Provider OAuth Settings
Each wearable provider requires OAuth credentials from their developer portal.
Suunto
SUUNTO_CLIENT_ID = public-client-id
SUUNTO_CLIENT_SECRET = private-secret-id
SUUNTO_SUBSCRIPTION_KEY = private-subscription-id
SUUNTO_REDIRECT_URI = http://localhost:8000/api/v1/oauth/suunto/callback
Setup: Suunto App Partner Portal
Polar
POLAR_CLIENT_ID = public-client-id
POLAR_CLIENT_SECRET = private-secret-id
POLAR_REDIRECT_URI = http://localhost:8000/api/v1/oauth/polar/callback
Setup: Polar AccessLink
Default scope: accesslink.read_all
Garmin
GARMIN_CLIENT_ID = your-garmin-client-id
GARMIN_CLIENT_SECRET = your-garmin-client-secret
GARMIN_REDIRECT_URI = http://localhost:8000/api/v1/oauth/garmin/callback
Setup: Garmin Developer Portal
Garmin scopes are configured at the application level in the Developer Portal, not via environment variables.
Whoop
WHOOP_CLIENT_ID = public-client-id
WHOOP_CLIENT_SECRET = private-secret-id
WHOOP_REDIRECT_URI = http://localhost:8000/api/v1/oauth/whoop/callback
WHOOP_DEFAULT_SCOPE = offline read :cycles read:sleep read:recovery read:workout
Setup: Whoop Developer Portal
Available scopes:
offline - Required for refresh tokens
read:cycles - Physiological cycles data
read:sleep - Sleep data
read:recovery - Recovery metrics
read:workout - Workout activities
Strava
STRAVA_CLIENT_ID = your-strava-client-id
STRAVA_CLIENT_SECRET = your-strava-client-secret
STRAVA_REDIRECT_URI = http://localhost:8000/api/v1/oauth/strava/callback
STRAVA_DEFAULT_SCOPE = activity:read_all,profile:read_all
STRAVA_WEBHOOK_VERIFY_TOKEN = open-wearables-strava-verify
Setup: Strava API Settings
Configuration:
STRAVA_WEBHOOK_VERIFY_TOKEN - Custom token for webhook verification
STRAVA_EVENTS_PER_PAGE - API pagination (default: 200, max: 200)
Strava requires webhook verification. The verify token must match when setting up webhook subscriptions.
OAuth Callback URLs
All OAuth providers require callback URLs to be registered in their developer portals:
http://localhost:8000/api/v1/oauth/ {provider} /callback
Supported providers: suunto, polar, garmin, whoop, strava
OAuth callback URLs must exactly match what’s registered in each provider’s developer portal, including protocol (http/https) and port numbers.
Sync Configuration
SYNC_INTERVAL_SECONDS = 3600 # 1 hour
Description: How often Celery Beat schedules automatic data synchronization from connected providers.
Recommended values:
Development: 3600 (1 hour)
Production: 1800 (30 minutes) to 7200 (2 hours)
Lower intervals provide more up-to-date data but increase API usage and costs. Most providers have rate limits.
AWS Configuration (Optional)
AWS_BUCKET_NAME = open-wearables
AWS_ACCESS_KEY_ID = your-access-id
AWS_SECRET_ACCESS_KEY = your-access-key
AWS_REGION = eu-north-1
SQS_QUEUE_URL = https://sqs.eu-north-1.amazonaws.com/12345678/xyz-queue
Description: AWS services for file storage and message queuing (optional features).
Services:
S3 - Store large data files and exports
SQS - Alternative message queue for Celery (instead of Redis)
S3 Bucket Policy: {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Action" : [
"s3:PutObject" ,
"s3:GetObject" ,
"s3:DeleteObject" ,
"s3:ListBucket"
],
"Resource" : [
"arn:aws:s3:::open-wearables/*" ,
"arn:aws:s3:::open-wearables"
]
}
]
}
SQS Queue Policy: {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Action" : [
"sqs:SendMessage" ,
"sqs:ReceiveMessage" ,
"sqs:DeleteMessage" ,
"sqs:GetQueueAttributes"
],
"Resource" : "arn:aws:sqs:eu-north-1:12345678:xyz-queue"
}
]
}
Error Tracking (Sentry)
SENTRY_ENABLED = True
SENTRY_DSN = ""
SENTRY_ENV = production
SENTRY_SAMPLES_RATE = 0.5
Description: Integration with Sentry for error tracking and performance monitoring.
Configuration:
Variable Description Default SENTRY_ENABLEDEnable/disable Sentry FalseSENTRY_DSNData Source Name from Sentry project Required if enabled SENTRY_ENVEnvironment tag for error grouping productionSENTRY_SAMPLES_RATEPerformance sampling rate (0.0 - 1.0) 0.5
Setup:
Create Sentry project
Sign up at sentry.io and create a new Python project
Copy DSN
Copy the DSN from your project settings
Configure environment
SENTRY_ENABLED = True
SENTRY_DSN = https://[email protected] /789
SENTRY_ENV = production
SENTRY_SAMPLES_RATE = 0.5
Sample rate determines what percentage of performance transactions are sent to Sentry. Lower values reduce data usage and costs while still capturing errors.
Advanced Settings
These settings have sensible defaults and typically don’t need modification:
# XML Processing
# XML_CHUNK_SIZE=50000 # Chunk size for parsing large XML files
# User Invitations
# USER_INVITATION_CODE_EXPIRE_DAYS=7 # Days until SDK invitation codes expire
Environment Variables Summary
Required for All Deployments
ENVIRONMENT
SECRET_KEY
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD
REDIS_HOST, REDIS_PORT
Required for Production
CORS_ORIGINS (your frontend URL)
SERVER_HOST (your API URL)
REDIS_PASSWORD (enable Redis auth)
Strong ADMIN_PASSWORD
Optional but Recommended
RESEND_API_KEY (for email functionality)
SENTRY_DSN (for error tracking)
Provider OAuth credentials (for wearable integrations)
Optional
AWS credentials (for S3 storage and SQS)
Custom sync intervals
Advanced configuration values
Security Best Practices
Critical Security Checklist:
Generate unique SECRET_KEY per environment
Use strong passwords for database and Redis
Never commit .env files to version control
Rotate secrets regularly (quarterly recommended)
Use managed services with encryption at rest
Enable Redis authentication in production
Restrict CORS origins to your domains only
Use HTTPS for all production deployments
Store secrets in a secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)
Implement least-privilege access for service accounts
Validation
Verify your configuration is working correctly:
# Check configuration is loaded
docker compose exec app python -c "from app.config import settings; print(settings.environment)"
# Test database connection
docker compose exec app python -c "from app.database import get_db; next(get_db())"
# Test Redis connection
docker compose exec app python -c "from redis import Redis; from app.config import settings; Redis.from_url(settings.redis_url).ping()"
# View loaded configuration (non-sensitive values)
curl http://localhost:8000/api/v1/health
Next Steps
Docker Deployment Deploy with Docker Compose
Database Setup Configure database and run migrations