Configuration Management
Comprehensive guide to managing application settings, environment variables, and configuration in FastLaunchAPI
Configuration Management
FastLaunchAPI uses a centralized configuration system that manages all application settings through environment variables and a singleton Settings class. This approach ensures secure, scalable, and environment-specific configuration management.
Overview
The configuration system is built around the Settings
class in app/config/settings.py
, which loads environment variables using python-dotenv
and provides typed access to all configuration values throughout the application.
All configuration values are loaded once at application startup and cached in
the app_settings
singleton instance for optimal performance.
Configuration Architecture
Settings Class Structure
The Settings
class centralizes all configuration management:
import os
from dotenv import load_dotenv
class Settings:
def __init__(self):
load_dotenv()
# Core Application Settings
self.SECRET_KEY: str = os.getenv("SECRET_KEY")
self.FRONTEND_URL: str = os.getenv("FRONTEND_URL")
self.BACKEND_URL: str = os.getenv("BACKEND_URL")
self.REDIS_DSN: str = os.getenv("REDIS_DSN")
# Security Configuration
self.CORS_ORIGINS: list[str] = ["*"]
self.ACCESS_TOKEN_EXPIRATION_DAYS: int = 7
self.REFRESH_TOKEN_EXPIRATION_DAYS: int = 14
# OAuth Configuration
self.GOOGLE_CLIENT_ID: str = os.getenv("GOOGLE_CLIENT_ID")
self.GOOGLE_CLIENT_SECRET: str = os.getenv("GOOGLE_CLIENT_SECRET")
self.GOOGLE_REDIRECT_URI: str = os.getenv("GOOGLE_REDIRECT_URI")
# Email Configuration
self.SENDGRID_API_KEY: str = os.getenv("SENDGRID_API_KEY")
# Singleton instance
app_settings = Settings()
Environment Variables
Required Variables
These environment variables are required for the application to function properly. Missing values will cause startup failures.
Variable | Description | Example |
---|---|---|
SECRET_KEY | JWT signing key and general encryption | your-super-secret-key-here |
DATABASE_URL | PostgreSQL connection string | postgresql://user:pass@localhost:5432/dbname |
FRONTEND_URL | Frontend application URL | http://localhost:3000 |
BACKEND_URL | Backend API URL | http://localhost:8000 |
Optional Variables (Still important for fully functionality)
Variable | Description | Default | Example |
---|---|---|---|
REDIS_DSN | Redis connection string | redis://localhost:6379 | redis://localhost:6379/0 |
CORS_ORIGINS | Allowed CORS origins | ["*"] | ["http://localhost:3000"] |
OAuth Configuration
For OAuth providers, configure the following variables:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8000/auth/callback/google
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_REDIRECT_URI=http://localhost:8000/auth/callback/github
Email Configuration
Configure email service providers:
SENDGRID_API_KEY=your-sendgrid-api-key
SENDGRID_FROM_EMAIL=noreply@yourdomain.com
Environment Setup
Create Environment File
Copy the sample environment file and customize it:
cp .env.sample .env
Configure Basic Settings
Update the .env
file with your specific values:
# Core Settings
SECRET_KEY=your-super-secret-key-here
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/fastlaunchapi
FRONTEND_URL=http://localhost:3000
BACKEND_URL=http://localhost:8000
# Redis (optional)
REDIS_DSN=redis://localhost:6379/0
# OAuth (optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8000/auth/callback/google
# Email (optional)
SENDGRID_API_KEY=your-sendgrid-api-key
Validate Configuration
The application will validate critical configuration on startup. Missing required variables will cause startup failures with clear error messages.
Using Configuration in Your Code
Importing Settings
Import the settings singleton in your modules:
from app.config.settings import app_settings
# Use configuration values
token_expiration = app_settings.ACCESS_TOKEN_EXPIRATION_DAYS
frontend_url = app_settings.FRONTEND_URL
Example Usage in Routes
Here's how configuration is used in authentication routes:
from app.config.settings import app_settings
@router.post("/token")
async def login_for_access_token(db: db_dependency, form_data: OAuth2PasswordRequestForm):
user = authenticate_user(form_data.username, form_data.password, db)
# Using configuration for token expiration
access_token = create_access_token(
user.username,
user.id,
timedelta(days=app_settings.ACCESS_TOKEN_EXPIRATION_DAYS)
)
# Using configuration for redirect URL
return RedirectResponse(f"{app_settings.FRONTEND_URL}/dashboard")
Configuration Categories
Core Application Settings
🔧 Core Settings
Essential application configuration
- SECRET_KEY: Used for JWT signing and encryption
- FRONTEND_URL: Frontend application URL for redirects
- BACKEND_URL: Backend API URL for internal references
- REDIS_DSN: Redis connection for caching and task queues
Security Configuration
🔒 Security Settings
Authentication and security parameters
- ACCESS_TOKEN_EXPIRATION_DAYS: JWT access token lifetime (default: 7 days)
- REFRESH_TOKEN_EXPIRATION_DAYS: JWT refresh token lifetime (default: 14 days)
- CORS_ORIGINS: Allowed cross-origin request sources
OAuth Provider Settings
🔐 OAuth Configuration
Third-party authentication provider settings
- GOOGLE_CLIENT_ID: Google OAuth client identifier
- GOOGLE_CLIENT_SECRET: Google OAuth client secret
- GOOGLE_REDIRECT_URI: OAuth callback URL
Email Service Configuration
📧 Email Settings
Email service provider configuration
- SENDGRID_API_KEY: SendGrid API key for email sending
- SENDGRID_FROM_EMAIL: Default sender email address
Environment-Specific Configuration
Development Environment
SECRET_KEY=development-secret-key
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/fastlaunchapi_dev
FRONTEND_URL=http://localhost:3000
BACKEND_URL=http://localhost:8000
REDIS_DSN=redis://localhost:6379/0
Production Environment
SECRET_KEY=${SECRET_KEY}
DATABASE_URL=${DATABASE_URL}
FRONTEND_URL=https://yourdomain.com
BACKEND_URL=https://api.yourdomain.com
REDIS_DSN=${REDIS_URL}
In production, use environment variables or secure secret management systems
instead of .env
files.
Advanced Configuration
Custom Configuration Values
Extend the Settings class to add custom configuration:
class Settings:
def __init__(self):
load_dotenv()
# Existing configuration...
# Custom configuration
self.MAX_UPLOAD_SIZE: int = int(os.getenv("MAX_UPLOAD_SIZE", "10485760")) # 10MB
self.RATE_LIMIT_REQUESTS: int = int(os.getenv("RATE_LIMIT_REQUESTS", "100"))
self.RATE_LIMIT_WINDOW: int = int(os.getenv("RATE_LIMIT_WINDOW", "3600")) # 1 hour
# Feature flags
self.ENABLE_REGISTRATION: bool = os.getenv("ENABLE_REGISTRATION", "true").lower() == "true"
self.ENABLE_OAUTH: bool = os.getenv("ENABLE_OAUTH", "true").lower() == "true"
Configuration Validation
Add validation to ensure configuration integrity:
import os
from typing import Optional
from dotenv import load_dotenv
class Settings:
def __init__(self):
load_dotenv()
# Load configuration
self.SECRET_KEY: str = os.getenv("SECRET_KEY")
self.DATABASE_URL: str = os.getenv("DATABASE_URL")
# Validate critical settings
self._validate_config()
def _validate_config(self):
"""Validate critical configuration values."""
if not self.SECRET_KEY:
raise ValueError("SECRET_KEY environment variable is required")
if not self.DATABASE_URL:
raise ValueError("DATABASE_URL environment variable is required")
if len(self.SECRET_KEY) < 32:
raise ValueError("SECRET_KEY must be at least 32 characters long")
Configuration Best Practices
Security Guidelines
Never commit sensitive configuration values to version control. Use environment variables or secure secret management systems.
Best Practices:
- Use strong SECRET_KEY: Generate a secure random key for production
- Environment separation: Use different configurations for dev/staging/production
- Secure secrets: Use secret management services in production
- Validate inputs: Add validation for critical configuration values
- Document defaults: Clearly document default values and requirements
Performance Considerations
- Singleton pattern: Configuration is loaded once at startup
- Type hints: Use type hints for better IDE support and validation
- Lazy loading: Only load configuration when needed
- Caching: Cache expensive configuration computations
Testing Configuration
Create test-specific configuration:
import pytest
from app.config.settings import Settings
@pytest.fixture
def test_settings():
"""Override settings for testing."""
settings = Settings()
settings.DATABASE_URL = "postgresql://test:test@localhost:5432/test_db"
settings.SECRET_KEY = "test-secret-key"
settings.ACCESS_TOKEN_EXPIRATION_DAYS = 1
return settings
Troubleshooting
Common Issues
Missing Environment Variables: Ensure all required environment variables are set before starting the application.
Invalid Configuration: Check that configuration values are properly formatted and within expected ranges.
Common Problems:
- SECRET_KEY not set: Application won't start without a valid SECRET_KEY
- Database connection: Verify DATABASE_URL format and database accessibility
- OAuth configuration: Ensure OAuth credentials are valid and redirect URIs match
- Port conflicts: Check that configured ports are available
Debug Configuration
Add logging to debug configuration issues:
import logging
import os
from dotenv import load_dotenv
logger = logging.getLogger(__name__)
class Settings:
def __init__(self):
load_dotenv()
# Log configuration loading
logger.info("Loading application configuration...")
self.SECRET_KEY: str = os.getenv("SECRET_KEY")
if not self.SECRET_KEY:
logger.error("SECRET_KEY not found in environment variables")
logger.info("Configuration loaded successfully")