# ============================================================================== # ThrillWiki Environment Configuration # ============================================================================== # Copy this file to .env and fill in your actual values # WARNING: Never commit .env files containing real secrets to version control # # This is the primary .env.example for the entire project. # See docs/configuration/environment-variables.md for complete documentation. # See docs/PRODUCTION_CHECKLIST.md for production deployment verification. # ============================================================================== # PRODUCTION-REQUIRED SETTINGS # ============================================================================== # These settings MUST be explicitly configured for production deployments. # The application will NOT function correctly without proper values. # # For complete documentation, see: # - docs/configuration/environment-variables.md (detailed reference) # - docs/PRODUCTION_CHECKLIST.md (deployment verification) # # PRODUCTION REQUIREMENTS: # - DEBUG=False (security) # - DJANGO_SETTINGS_MODULE=config.django.production (correct settings) # - ALLOWED_HOSTS=yourdomain.com (host validation) # - CSRF_TRUSTED_ORIGINS=https://yourdomain.com (CSRF protection) # - REDIS_URL=redis://host:6379/0 (caching/sessions) # - SECRET_KEY= (cryptographic security) # - DATABASE_URL=postgis://... (database connection) # # Validate your production config with: # DJANGO_SETTINGS_MODULE=config.django.production python manage.py check --deploy # ============================================================================== # ============================================================================== # Core Django Settings # ============================================================================== # REQUIRED: Django secret key - generate a new one for each environment # Generate with: python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" SECRET_KEY=your-secret-key-here-generate-a-new-one # Debug mode - MUST be False in production # WARNING: DEBUG=True exposes sensitive information and should NEVER be used in production DEBUG=True # Django settings module to use # Options: config.django.local, config.django.production, config.django.test # PRODUCTION: Must use config.django.production DJANGO_SETTINGS_MODULE=config.django.local # Allowed hosts (comma-separated list) # PRODUCTION: Must include all valid hostnames (no default in production settings) # Example: thrillwiki.com,www.thrillwiki.com,api.thrillwiki.com ALLOWED_HOSTS=localhost,127.0.0.1,beta.thrillwiki.com # CSRF trusted origins (comma-separated, MUST include https:// prefix) # PRODUCTION: Required for all forms and AJAX requests to work # Example: https://thrillwiki.com,https://www.thrillwiki.com CSRF_TRUSTED_ORIGINS=https://beta.thrillwiki.com,http://localhost:8000 # ============================================================================== # Database Configuration # ============================================================================== # Database URL (supports PostgreSQL, PostGIS, SQLite, SpatiaLite) # PostGIS format: postgis://username:password@host:port/database # PostgreSQL format: postgres://username:password@host:port/database # SQLite format: sqlite:///path/to/db.sqlite3 DATABASE_URL=postgis://username:password@localhost:5432/thrillwiki # Database connection pooling (seconds to keep connections alive) # Set to 0 to disable connection reuse DATABASE_CONN_MAX_AGE=600 # Database connection timeout in seconds DATABASE_CONNECT_TIMEOUT=10 # Query timeout in milliseconds (prevents long-running queries) DATABASE_STATEMENT_TIMEOUT=30000 # Optional: Read replica URL for read-heavy workloads # DATABASE_READ_REPLICA_URL=postgis://username:password@replica-host:5432/thrillwiki # ============================================================================== # Cache Configuration # ============================================================================== # Redis URL for caching, sessions, and Celery broker # Format: redis://[:password@]host:port/db_number # PRODUCTION: Required - the application uses Redis for: # - Page and API response caching # - Session storage (faster than database sessions) # - Celery task queue broker # Without REDIS_URL in production, caching will fail and performance will degrade. REDIS_URL=redis://localhost:6379/1 # Optional: Separate Redis URLs for different cache purposes # REDIS_SESSIONS_URL=redis://localhost:6379/2 # REDIS_API_URL=redis://localhost:6379/3 # Redis connection settings REDIS_MAX_CONNECTIONS=100 REDIS_CONNECTION_TIMEOUT=20 REDIS_IGNORE_EXCEPTIONS=True # Cache middleware settings CACHE_MIDDLEWARE_SECONDS=300 CACHE_MIDDLEWARE_KEY_PREFIX=thrillwiki CACHE_KEY_PREFIX=thrillwiki # Local development cache URL (use for development without Redis) # CACHE_URL=locmem:// # ============================================================================== # Email Configuration # ============================================================================== # Email backend # Options: # django.core.mail.backends.console.EmailBackend (development) # django_forwardemail.backends.ForwardEmailBackend (production with ForwardEmail) # django.core.mail.backends.smtp.EmailBackend (custom SMTP) EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend # Server email address SERVER_EMAIL=django_webmaster@thrillwiki.com # Default from email DEFAULT_FROM_EMAIL=ThrillWiki # Email subject prefix for admin emails EMAIL_SUBJECT_PREFIX=[ThrillWiki] # ForwardEmail configuration (for ForwardEmailBackend) FORWARD_EMAIL_BASE_URL=https://api.forwardemail.net FORWARD_EMAIL_API_KEY=your-forwardemail-api-key-here FORWARD_EMAIL_DOMAIN=your-domain.com # SMTP configuration (for SMTPBackend) EMAIL_HOST=smtp.example.com EMAIL_PORT=587 EMAIL_USE_TLS=True EMAIL_USE_SSL=False EMAIL_HOST_USER=your-email@example.com EMAIL_HOST_PASSWORD=your-app-password # Email timeout in seconds EMAIL_TIMEOUT=30 # ============================================================================== # Security Settings # ============================================================================== # Cloudflare Turnstile configuration (CAPTCHA alternative) # Get keys from: https://dash.cloudflare.com/?to=/:account/turnstile TURNSTILE_SITE_KEY=your-turnstile-site-key TURNSTILE_SECRET_KEY=your-turnstile-secret-key TURNSTILE_VERIFY_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify # SSL/HTTPS settings (enable all for production) SECURE_SSL_REDIRECT=False SESSION_COOKIE_SECURE=False CSRF_COOKIE_SECURE=False # HSTS settings (HTTP Strict Transport Security) SECURE_HSTS_SECONDS=31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS=True SECURE_HSTS_PRELOAD=False # Security headers SECURE_BROWSER_XSS_FILTER=True SECURE_CONTENT_TYPE_NOSNIFF=True X_FRAME_OPTIONS=DENY SECURE_REFERRER_POLICY=strict-origin-when-cross-origin SECURE_CROSS_ORIGIN_OPENER_POLICY=same-origin # Session settings SESSION_COOKIE_AGE=3600 SESSION_SAVE_EVERY_REQUEST=True SESSION_COOKIE_HTTPONLY=True SESSION_COOKIE_SAMESITE=Lax # CSRF settings CSRF_COOKIE_HTTPONLY=True CSRF_COOKIE_SAMESITE=Lax # Password minimum length PASSWORD_MIN_LENGTH=8 # ============================================================================== # GeoDjango Settings # ============================================================================== # Library paths for GDAL and GEOS (required for GeoDjango) # macOS with Homebrew: GDAL_LIBRARY_PATH=/opt/homebrew/lib/libgdal.dylib GEOS_LIBRARY_PATH=/opt/homebrew/lib/libgeos_c.dylib # Linux alternatives: # GDAL_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/libgdal.so # GEOS_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/libgeos_c.so # ============================================================================== # API Configuration # ============================================================================== # CORS settings CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5174 CORS_ALLOW_ALL_ORIGINS=False # API rate limiting API_RATE_LIMIT_PER_MINUTE=60 API_RATE_LIMIT_PER_HOUR=1000 API_RATE_LIMIT_ANON_PER_MINUTE=60 API_RATE_LIMIT_USER_PER_HOUR=1000 # API pagination API_PAGE_SIZE=20 API_MAX_PAGE_SIZE=100 API_VERSION=1.0.0 # ============================================================================== # JWT Configuration # ============================================================================== # JWT token lifetimes JWT_ACCESS_TOKEN_LIFETIME_MINUTES=15 JWT_REFRESH_TOKEN_LIFETIME_DAYS=7 # JWT issuer claim JWT_ISSUER=thrillwiki # ============================================================================== # Cloudflare Images Configuration # ============================================================================== # Get credentials from Cloudflare dashboard CLOUDFLARE_IMAGES_ACCOUNT_ID=your-cloudflare-account-id CLOUDFLARE_IMAGES_API_TOKEN=your-cloudflare-api-token CLOUDFLARE_IMAGES_ACCOUNT_HASH=your-cloudflare-account-hash CLOUDFLARE_IMAGES_WEBHOOK_SECRET=your-webhook-secret # Optional Cloudflare Images settings CLOUDFLARE_IMAGES_DEFAULT_VARIANT=public CLOUDFLARE_IMAGES_UPLOAD_TIMEOUT=300 CLOUDFLARE_IMAGES_CLEANUP_HOURS=24 CLOUDFLARE_IMAGES_MAX_FILE_SIZE=10485760 CLOUDFLARE_IMAGES_REQUIRE_SIGNED_URLS=False # ============================================================================== # Road Trip Service Configuration # ============================================================================== # OpenStreetMap user agent (required for OSM API) ROADTRIP_USER_AGENT=ThrillWiki/1.0 (https://thrillwiki.com) # Cache timeouts ROADTRIP_CACHE_TIMEOUT=86400 ROADTRIP_ROUTE_CACHE_TIMEOUT=21600 # Request settings ROADTRIP_MAX_REQUESTS_PER_SECOND=1 ROADTRIP_REQUEST_TIMEOUT=10 ROADTRIP_MAX_RETRIES=3 ROADTRIP_BACKOFF_FACTOR=2 # ============================================================================== # Logging Configuration # ============================================================================== # Log directory (relative to backend/) LOG_DIR=logs # Log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL) ROOT_LOG_LEVEL=INFO DJANGO_LOG_LEVEL=WARNING DB_LOG_LEVEL=WARNING APP_LOG_LEVEL=INFO PERFORMANCE_LOG_LEVEL=INFO QUERY_LOG_LEVEL=WARNING NPLUSONE_LOG_LEVEL=WARNING REQUEST_LOG_LEVEL=INFO CELERY_LOG_LEVEL=INFO CONSOLE_LOG_LEVEL=INFO FILE_LOG_LEVEL=INFO # Log formatters (verbose, json, simple) FILE_LOG_FORMATTER=json # ============================================================================== # Monitoring & Errors # ============================================================================== # Sentry configuration (optional, for error tracking) # SENTRY_DSN=https://your-sentry-dsn-here # SENTRY_ENVIRONMENT=development # SENTRY_TRACES_SAMPLE_RATE=0.1 # ============================================================================== # Feature Flags # ============================================================================== # Development tools ENABLE_DEBUG_TOOLBAR=True ENABLE_SILK_PROFILER=False # Django template support (can be disabled for API-only mode) TEMPLATES_ENABLED=True # Autocomplete settings AUTOCOMPLETE_BLOCK_UNAUTHENTICATED=False # ============================================================================== # Third-Party Configuration # ============================================================================== # Frontend URL for email links and redirects FRONTEND_DOMAIN=https://thrillwiki.com # Login/logout redirect URLs LOGIN_REDIRECT_URL=/ ACCOUNT_LOGOUT_REDIRECT_URL=/ # Account settings ACCOUNT_EMAIL_VERIFICATION=mandatory # ============================================================================== # File Upload Settings # ============================================================================== # Maximum file size to upload into memory (bytes) FILE_UPLOAD_MAX_MEMORY_SIZE=2621440 # Maximum request data size (bytes) DATA_UPLOAD_MAX_MEMORY_SIZE=10485760 # Maximum number of GET/POST parameters DATA_UPLOAD_MAX_NUMBER_FIELDS=1000 # Static/Media URLs (usually don't need to change) STATIC_URL=static/ MEDIA_URL=/media/ # WhiteNoise settings WHITENOISE_COMPRESSION_QUALITY=90 WHITENOISE_MAX_AGE=31536000 WHITENOISE_MANIFEST_STRICT=False # ============================================================================== # Health Check Settings # ============================================================================== # Disk usage threshold (percentage) HEALTH_CHECK_DISK_USAGE_MAX=90 # Minimum available memory (MB) HEALTH_CHECK_MEMORY_MIN=100 # ============================================================================== # Celery Configuration # ============================================================================== # Celery task behavior (set to True for testing) CELERY_TASK_ALWAYS_EAGER=False CELERY_TASK_EAGER_PROPAGATES=False # ============================================================================== # Debug Toolbar Configuration # ============================================================================== # Internal IPs for debug toolbar (comma-separated) # INTERNAL_IPS=127.0.0.1,::1