Skip to main content

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

.env
ENVIRONMENT="local"
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

.env
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

.env
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

.env
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

.env
# 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

.env
DB_HOST=db
DB_PORT=5432
DB_NAME=open-wearables
DB_USER=open-wearables
DB_PASSWORD=open-wearables
# 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

.env
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)

.env
# 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

.env
# 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)

.env
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:
1

Sign up at resend.com

Create a free account at resend.com
2

Add your domain

Add and verify your sending domain in the Resend dashboard
3

Generate API key

Create an API key and copy it to RESEND_API_KEY
4

Configure sender

Update EMAIL_FROM_ADDRESS to use your verified domain
Configuration options:
VariableDescriptionExample
RESEND_API_KEYAPI key from Resend dashboardre_123abc...
EMAIL_FROM_ADDRESSSender email address[email protected]
EMAIL_FROM_NAMESender display nameOpen Wearables
FRONTEND_URLFrontend base URL for email linkshttps://app.example.com
INVITATION_EXPIRE_DAYSDays until invitation expires (default: 7)7
EMAIL_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

.env
ADMIN_EMAIL=[email protected]
ADMIN_PASSWORD=your-secure-password
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

.env
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

.env
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

.env
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

.env
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

.env
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

.env
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)

.env
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)

.env
SENTRY_ENABLED=True
SENTRY_DSN=""
SENTRY_ENV=production
SENTRY_SAMPLES_RATE=0.5
Description: Integration with Sentry for error tracking and performance monitoring. Configuration:
VariableDescriptionDefault
SENTRY_ENABLEDEnable/disable SentryFalse
SENTRY_DSNData Source Name from Sentry projectRequired if enabled
SENTRY_ENVEnvironment tag for error groupingproduction
SENTRY_SAMPLES_RATEPerformance sampling rate (0.0 - 1.0)0.5
Setup:
1

Create Sentry project

Sign up at sentry.io and create a new Python project
2

Copy DSN

Copy the DSN from your project settings
3

Configure environment

.env
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:
.env
# 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
  • 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:
  1. Generate unique SECRET_KEY per environment
  2. Use strong passwords for database and Redis
  3. Never commit .env files to version control
  4. Rotate secrets regularly (quarterly recommended)
  5. Use managed services with encryption at rest
  6. Enable Redis authentication in production
  7. Restrict CORS origins to your domains only
  8. Use HTTPS for all production deployments
  9. Store secrets in a secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)
  10. 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

Build docs developers (and LLMs) love