# Configuration System This project uses a comprehensive TOML-based configuration system with environment variable overrides. The configuration system supports multiple environments, feature flags, and secure credential management. ## Quick Start 1. Copy one of the example configuration files to `config.toml`: ```bash cp config.dev.toml config.toml ``` 2. Set environment-specific variables: ```bash export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb" export SESSION_SECRET="your-secret-key-here" ``` 3. Run your application: ```bash cargo run ``` ## Configuration Files ### File Priority The configuration system looks for files in this order: 1. `$CONFIG_FILE` (if environment variable is set) 2. `config.{environment}.toml` (e.g., `config.dev.toml`, `config.prod.toml`) 3. `config.toml` (default fallback) ### Environment Detection The environment is determined by the `ENVIRONMENT` variable: - `development` or `dev` → looks for `config.dev.toml` - `production` or `prod` → looks for `config.prod.toml` - Default → looks for `config.toml` ## Configuration Structure ### Server Configuration ```toml [server] protocol = "http" # "http" or "https" host = "127.0.0.1" # Server bind address port = 3030 # Server port environment = "development" # "development" or "production" log_level = "info" # "trace", "debug", "info", "warn", "error" # TLS Configuration (required when protocol = "https") [server.tls] cert_path = "certs/server.crt" key_path = "certs/server.key" ``` ### Database Configuration ```toml [database] url = "postgresql://user:pass@localhost:5432/dbname" max_connections = 10 min_connections = 1 connect_timeout = 30 # seconds idle_timeout = 600 # seconds max_lifetime = 1800 # seconds ``` ### Session Configuration ```toml [session] secret = "your-session-secret-here" cookie_name = "session_id" cookie_secure = false # Set to true in production with HTTPS cookie_http_only = true cookie_same_site = "lax" # "strict", "lax", or "none" max_age = 3600 # Session duration in seconds ``` ### CORS Configuration ```toml [cors] allowed_origins = ["http://localhost:3030"] allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"] allowed_headers = ["Content-Type", "Authorization"] allow_credentials = true max_age = 3600 ``` ### Security Configuration ```toml [security] enable_csrf = true csrf_token_name = "csrf_token" rate_limit_requests = 100 # Requests per window rate_limit_window = 60 # Window size in seconds bcrypt_cost = 12 # BCrypt hashing cost ``` ### OAuth Configuration ```toml [oauth] enabled = true [oauth.google] client_id = "your-google-client-id" client_secret = "your-google-client-secret" redirect_uri = "http://localhost:3030/auth/google/callback" [oauth.github] client_id = "your-github-client-id" client_secret = "your-github-client-secret" redirect_uri = "http://localhost:3030/auth/github/callback" ``` ### Email Configuration ```toml [email] # Enable/disable email functionality enabled = true # Email provider: "smtp", "sendgrid", or "console" provider = "console" # Default sender information from_email = "noreply@yourapp.com" from_name = "Your App Name" # Template directory for internationalized email templates template_dir = "templates/email" # SMTP Configuration (when provider = "smtp") smtp_host = "smtp.gmail.com" smtp_port = 587 smtp_username = "your-email@gmail.com" smtp_password = "your-app-password" smtp_use_tls = false smtp_use_starttls = true # SendGrid Configuration (when provider = "sendgrid") sendgrid_api_key = "" sendgrid_endpoint = "https://api.sendgrid.com/v3/mail/send" # Environment-specific email settings [environments.development] email.enabled = true email.provider = "console" [environments.production] email.enabled = true email.provider = "sendgrid" email.sendgrid_api_key = "${SENDGRID_API_KEY}" email.from_email = "noreply@yourdomain.com" ``` ### Feature Flags ```toml [features] auth = true # Enable authentication tls = false # Enable TLS support content_db = true # Enable database content management two_factor_auth = false # Enable 2FA email = true # Enable email functionality ``` ## Environment Variable Overrides Environment variables take precedence over TOML file values. Use the following format: ### Server Overrides - `SERVER_PROTOCOL` → `server.protocol` - `SERVER_HOST` → `server.host` - `SERVER_PORT` → `server.port` - `ENVIRONMENT` → `server.environment` - `LOG_LEVEL` → `server.log_level` ### TLS Overrides - `TLS_CERT_PATH` → `server.tls.cert_path` - `TLS_KEY_PATH` → `server.tls.key_path` ### Database Overrides - `DATABASE_URL` → `database.url` ### Session Overrides - `SESSION_SECRET` → `session.secret` ### Example Environment Variables ```bash # Server configuration export SERVER_HOST="0.0.0.0" export SERVER_PORT="8080" export ENVIRONMENT="production" export SERVER_PROTOCOL="https" # Database export DATABASE_URL="postgresql://prod_user:${DB_PASSWORD}@db.example.com:5432/prod_db" # Security export SESSION_SECRET="super-secret-production-key" export TLS_CERT_PATH="/etc/ssl/certs/server.crt" export TLS_KEY_PATH="/etc/ssl/private/server.key" # OAuth export GOOGLE_CLIENT_ID="your-google-client-id" export GOOGLE_CLIENT_SECRET="your-google-client-secret" export GITHUB_CLIENT_ID="your-github-client-id" export GITHUB_CLIENT_SECRET="your-github-client-secret" # Email export EMAIL_PROVIDER="sendgrid" export EMAIL_FROM_ADDRESS="noreply@yourdomain.com" export EMAIL_FROM_NAME="Your Production App" export SENDGRID_API_KEY="your-sendgrid-api-key" export SMTP_HOST="smtp.gmail.com" export SMTP_USERNAME="your-email@gmail.com" export SMTP_PASSWORD="your-app-password" ``` ## Environment Variable Substitution You can use environment variable substitution in TOML files: ```toml [database] url = "postgresql://user:${DATABASE_PASSWORD}@localhost:5432/db" [session] secret = "${SESSION_SECRET}" [oauth.google] client_id = "${GOOGLE_CLIENT_ID}" client_secret = "${GOOGLE_CLIENT_SECRET}" [email] provider = "${EMAIL_PROVIDER}" from_email = "${EMAIL_FROM_ADDRESS}" sendgrid_api_key = "${SENDGRID_API_KEY}" smtp_password = "${SMTP_PASSWORD}" ``` ## Usage in Code ### Loading Configuration ```rust use server::config::Config; #[tokio::main] async fn main() -> Result<(), Box> { // Load configuration let config = Config::load()?; // Use configuration println!("Server: {}:{}", config.server.host, config.server.port); println!("Database: {}", config.database.url); Ok(()) } ``` ### Configuration Methods ```rust let config = Config::load()?; // Helper methods let server_addr = config.server_address(); // "127.0.0.1:3030" let server_url = config.server_url(); // "http://127.0.0.1:3030" let is_dev = config.is_development(); // true/false let is_prod = config.is_production(); // true/false let needs_tls = config.requires_tls(); // true/false // Database pool configuration let pool_config = config.database_pool_config(); // Email configuration let email_enabled = config.email.enabled; let email_provider = &config.email.provider; let template_dir = &config.email.template_dir; ``` ### Custom Configuration ```rust let custom_config = Config { server: ServerConfig { protocol: Protocol::Http, host: "localhost".to_string(), port: 3000, environment: Environment::Development, log_level: "debug".to_string(), tls: None, }, app: AppConfig { name: "My App".to_string(), version: "1.0.0".to_string(), debug: true, ..Default::default() }, ..Default::default() }; ``` ## Best Practices ### Development 1. Use `config.dev.toml` for development settings 2. Enable debug logging and relaxed security 3. Use local database connections 4. Disable TLS for easier development ### Production 1. Use `config.prod.toml` for production settings 2. Enable all security features 3. Use environment variables for secrets 4. Enable TLS and secure cookies 5. Use restrictive CORS policies ### Security 1. **Never commit secrets to version control** 2. Use environment variables for sensitive data 3. Use strong session secrets (32+ characters) 4. Enable CSRF protection in production 5. Use secure cookies with HTTPS 6. Implement rate limiting ### Docker ```dockerfile # Copy configuration files COPY config.prod.toml /app/config.toml # Set environment variables ENV ENVIRONMENT=production ENV DATABASE_URL=${DATABASE_URL} ENV SESSION_SECRET=${SESSION_SECRET} ``` ### Kubernetes ```yaml apiVersion: v1 kind: ConfigMap metadata: name: app-config data: config.toml: | [server] protocol = "https" host = "0.0.0.0" port = 8080 environment = "production" [database] url = "postgresql://user:${DATABASE_PASSWORD}@postgres:5432/app" --- apiVersion: v1 kind: Secret metadata: name: app-secrets data: DATABASE_PASSWORD: SESSION_SECRET: ``` ## Configuration Examples ### Development Environment ```toml [server] protocol = "http" host = "127.0.0.1" port = 3030 environment = "development" log_level = "debug" [database] url = "postgresql://dev:dev@localhost:5432/app_dev" max_connections = 5 [security] enable_csrf = false rate_limit_requests = 1000 bcrypt_cost = 4 [session] cookie_secure = false max_age = 7200 [email] enabled = true provider = "console" template_dir = "templates/email" ``` ### Production Environment ```toml [server] protocol = "https" host = "0.0.0.0" port = 443 environment = "production" log_level = "info" [server.tls] cert_path = "/etc/ssl/certs/app.crt" key_path = "/etc/ssl/private/app.key" [database] url = "postgresql://app:${DATABASE_PASSWORD}@db.example.com:5432/app_prod" max_connections = 20 [security] enable_csrf = true rate_limit_requests = 50 bcrypt_cost = 12 [session] secret = "${SESSION_SECRET}" cookie_secure = true cookie_same_site = "strict" max_age = 3600 [email] enabled = true provider = "sendgrid" sendgrid_api_key = "${SENDGRID_API_KEY}" from_email = "noreply@yourdomain.com" from_name = "Your Production App" template_dir = "templates/email" ``` ## Troubleshooting ### Configuration Not Found ``` Error: Configuration file not found: config.toml ``` **Solution:** Create a configuration file or set the `CONFIG_FILE` environment variable. ### Environment Variable Not Found ``` Error: Environment variable 'DATABASE_PASSWORD' not found ``` **Solution:** Set the required environment variable or remove the substitution from the TOML file. ### TLS Configuration Error ``` Error: TLS certificate path is required when using HTTPS ``` **Solution:** Either set `protocol = "http"` or provide valid TLS certificate paths. ### Database Connection Error ``` Error: Failed to connect to database ``` **Solution:** Check the database URL and ensure the database is running and accessible. ## Migration from Environment-Only Configuration If you're migrating from a purely environment-based configuration: 1. Create a `config.toml` file with your current settings 2. Move sensitive values to environment variables 3. Use environment variable substitution in TOML 4. Test the configuration loading Example migration: ```bash # Old way (environment only) export SERVER_HOST="0.0.0.0" export SERVER_PORT="3030" export DATABASE_URL="postgresql://..." # New way (TOML + environment) # config.toml [server] host = "0.0.0.0" port = 3030 [database] url = "${DATABASE_URL}" ``` ## Testing Configuration Run the configuration example to test your setup: ```bash cargo run --example config_example ``` This will show you how your configuration is being loaded and what values are being used. ## Email Template Configuration The email system uses an internationalized template structure with automatic language fallback: ### Template Directory Structure ``` templates/email/ ├── en_/ # English templates (default) │ ├── html/ # HTML email templates │ │ ├── contact.hbs # Contact form template │ │ └── notification.hbs # Notification template │ └── text/ # Plain text templates │ ├── contact.hbs │ └── notification.hbs ├── es_/ # Spanish templates │ ├── html/ │ └── text/ └── README.md # Template documentation ``` ### Template Naming Convention Templates are registered with the pattern: `{language}_{template_name}_{format}` Examples: - `en_contact_html` - English contact form HTML template - `es_notification_text` - Spanish notification text template ### Language Detection and Fallback The system automatically detects language preferences from: 1. **User Profile**: Authenticated user's saved language preference 2. **Request Headers**: `Accept-Language` HTTP header 3. **Default Fallback**: English (`en`) ### Template Configuration ```toml [email] # Template directory (relative to project root) template_dir = "templates/email" # Default language for fallback default_language = "en" # Supported languages supported_languages = ["en", "es", "fr", "de"] ``` ### Creating New Templates 1. **Create language directory:** ```bash mkdir -p templates/email/fr_/html mkdir -p templates/email/fr_/text ``` 2. **Add template files:** ```bash # Create French contact template touch templates/email/fr_/html/contact.hbs touch templates/email/fr_/text/contact.hbs ``` 3. **Template variables:** ```handlebars {{name}} # User's name {{email}} # User's email {{subject}} # Message subject {{message}} # Message content {{submitted_at}} # Timestamp ``` ### Available Handlebars Helpers - `{{date_format submitted_at "%B %d, %Y at %I:%M %p UTC"}}` - `{{capitalize form_type}}` - `{{truncate user_agent 100}}` - `{{default action_text "Click Here"}}` - `{{url_encode email}}` ### Environment-Specific Email Settings ```toml # Development - Print emails to console [environments.development] email.enabled = true email.provider = "console" # Staging - Use test SMTP server [environments.staging] email.enabled = true email.provider = "smtp" email.smtp_host = "smtp.mailtrap.io" email.smtp_port = 2525 # Production - Use SendGrid [environments.production] email.enabled = true email.provider = "sendgrid" email.sendgrid_api_key = "${SENDGRID_API_KEY}" ``` For detailed email template documentation, see `templates/email/README.md`. ## Configuration Encryption System The Rustelo framework includes a comprehensive encryption system for securing sensitive configuration values using AES-256-GCM encryption with automatic key management. ### Overview The encryption system provides: - **AES-256-GCM encryption** for sensitive configuration values - **Automatic key generation** and management via `.k` file - **Simple syntax** - encrypted values start with `@` - **Automatic decryption** during configuration loading - **CLI tools** for managing encrypted values - **Environment variable compatibility** alongside encryption ### Quick Start 1. **Generate Encryption Key**: ```bash cargo run --bin config_crypto_tool generate-key ``` 2. **Encrypt Sensitive Values**: ```bash cargo run --bin config_crypto_tool encrypt "my_secret_password" # Output: @AbCdEf123456... ``` 3. **Use in Configuration**: ```toml [session] secret = "@AbCdEf123456..." [database] url = "postgresql://user:@ZW5jcnlwdGVk@localhost:5432/db" ``` 4. **Verify Setup**: ```bash cargo run --bin config_crypto_tool verify ``` ### Encryption Integration in Configuration Configuration values starting with `@` are automatically decrypted during loading: ```toml # config.prod.toml [session] secret = "@c2Vzc2lvbl9zZWNyZXRfZXhhbXBsZQ==" # Encrypted session secret [database] url = "postgresql://user:@ZW5jcnlwdGVkX3Bhc3N3b3Jk@localhost:5432/mydb" [oauth.google] client_id = "${GOOGLE_CLIENT_ID}" # Environment variable client_secret = "@Z29vZ2xlX2NsaWVudF9zZWNyZXQ=" # Encrypted value [email] sendgrid_api_key = "@c2VuZGdyaWRfYXBpX2tleQ==" smtp_password = "@c210cF9wYXNzd29yZA==" ``` ### Mixed Configuration Approach You can combine encrypted values with environment variables for maximum flexibility: ```toml [database] url = "${DATABASE_URL}" # Environment variable (highest priority) [session] secret = "@encrypted_session_secret" # Encrypted value [oauth.google] client_id = "${GOOGLE_CLIENT_ID}" # Environment variable client_secret = "@encrypted_google_secret" # Encrypted value [redis] url = "@encrypted_redis_url" # Encrypted Redis URL with credentials ``` ### Configuration Loading Order 1. **Environment variables** (highest priority) 2. **Encrypted values** (decrypted automatically) 3. **Plain text values** (lowest priority) The framework includes a built-in encryption system for securing sensitive configuration values using AES-256-GCM encryption. ### How It Works 1. **Encryption Key**: A `.k` file in the project root contains the encryption key 2. **Encrypted Values**: Configuration values starting with `@` are automatically decrypted 3. **Automatic Management**: The system handles key generation and value decryption seamlessly ### Quick Start ```bash # Generate encryption key cargo run --bin config_crypto_tool generate-key # Encrypt a sensitive value cargo run --bin config_crypto_tool encrypt "your_secret_value" # Output: @AbCdEf123456... # Use in configuration echo 'session.secret = "@AbCdEf123456..."' >> config.toml # Verify encryption works cargo run --bin config_crypto_tool verify ``` ### Configuration Examples ```toml # Example encrypted configuration [session] secret = "@encrypted_session_secret" [database] url = "postgresql://user:@encrypted_password@localhost:5432/db" [oauth.google] client_secret = "@encrypted_google_client_secret" [email] sendgrid_api_key = "@encrypted_sendgrid_api_key" smtp_password = "@encrypted_smtp_password" ``` ### CLI Commands ```bash # Key management cargo run --bin config_crypto_tool generate-key # Generate new key cargo run --bin config_crypto_tool key-info # Show key information cargo run --bin config_crypto_tool verify # Verify key works cargo run --bin config_crypto_tool rotate-key --confirm # Rotate key # Value encryption/decryption cargo run --bin config_crypto_tool encrypt "value" # Encrypt a value cargo run --bin config_crypto_tool decrypt "@..." # Decrypt a value # Configuration management cargo run --bin config_crypto_tool find-encrypted -c config.toml cargo run --bin config_crypto_tool show-decrypted -c config.toml cargo run --bin config_crypto_tool encrypt-config -c config.toml -k "secret,api_key" # Interactive mode cargo run --bin config_crypto_tool interactive ``` ### Security Features - **AES-256-GCM encryption** with authenticated encryption - **Automatic key generation** using cryptographically secure random numbers - **File permissions** set to 0600 (read/write for owner only) - **Key rotation support** with backup creation - **Environment variable compatibility** - can mix encrypted and environment values ### Best Practices 1. **Never commit `.k` files** to version control 2. **Use different keys** for different environments 3. **Backup encryption keys** securely 4. **Rotate keys regularly** in production 5. **Monitor key file integrity** ### Mixed Configuration Approach You can combine encrypted values with environment variables: ```toml [database] url = "${DATABASE_URL}" # Environment variable [session] secret = "@encrypted_session_secret" # Encrypted value [oauth.google] client_id = "${GOOGLE_CLIENT_ID}" # Environment variable client_secret = "@encrypted_google_secret" # Encrypted value ``` ### Deployment Considerations ```bash # Production deployment # 1. Generate key on production server cargo run --bin config_crypto_tool generate-key # 2. Encrypt production secrets PROD_SECRET=$(cargo run --bin config_crypto_tool encrypt "prod-secret-2024") # 3. Update configuration with encrypted values # 4. Ensure .k file is properly secured and backed up ``` ### File Structure ``` project/ ├── .k # Encryption key (DO NOT COMMIT) ├── config.prod.toml # Config with encrypted values ├── .gitignore # Must include .k └── docs/ └── ENCRYPTION.md # Detailed encryption documentation ``` ### Error Handling Common issues and solutions: - **Key not found**: Run `cargo run --bin config_crypto_tool generate-key` - **Decryption failed**: Verify key with `cargo run --bin config_crypto_tool verify` - **Permission denied**: Set proper permissions with `chmod 600 .k` For comprehensive encryption documentation, see `docs/ENCRYPTION.md`.