- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
20 KiB
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
-
Copy one of the example configuration files to
config.toml:cp config.dev.toml config.toml -
Set environment-specific variables:
export DATABASE_URL="postgresql://user:pass@localhost:5432/mydb" export SESSION_SECRET="your-secret-key-here" -
Run your application:
cargo run
Configuration Files
File Priority
The configuration system looks for files in this order:
$CONFIG_FILE(if environment variable is set)config.{environment}.toml(e.g.,config.dev.toml,config.prod.toml)config.toml(default fallback)
Environment Detection
The environment is determined by the ENVIRONMENT variable:
developmentordev→ looks forconfig.dev.tomlproductionorprod→ looks forconfig.prod.toml- Default → looks for
config.toml
Configuration Structure
Server Configuration
[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
[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
[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
[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
[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
[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
[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
[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.protocolSERVER_HOST→server.hostSERVER_PORT→server.portENVIRONMENT→server.environmentLOG_LEVEL→server.log_level
TLS Overrides
TLS_CERT_PATH→server.tls.cert_pathTLS_KEY_PATH→server.tls.key_path
Database Overrides
DATABASE_URL→database.url
Session Overrides
SESSION_SECRET→session.secret
Example Environment Variables
# 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:
[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
use server::config::Config;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load configuration
let config = Config::load()?;
// Use configuration
println!("Server: {}:{}", config.server.host, config.server.port);
println!("Database: {}", config.database.url);
Ok(())
}
Configuration Methods
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
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
- Use
config.dev.tomlfor development settings - Enable debug logging and relaxed security
- Use local database connections
- Disable TLS for easier development
Production
- Use
config.prod.tomlfor production settings - Enable all security features
- Use environment variables for secrets
- Enable TLS and secure cookies
- Use restrictive CORS policies
Security
- Never commit secrets to version control
- Use environment variables for sensitive data
- Use strong session secrets (32+ characters)
- Enable CSRF protection in production
- Use secure cookies with HTTPS
- Implement rate limiting
Docker
# 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
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: <base64-encoded-password>
SESSION_SECRET: <base64-encoded-secret>
Configuration Examples
Development Environment
[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
[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:
- Create a
config.tomlfile with your current settings - Move sensitive values to environment variables
- Use environment variable substitution in TOML
- Test the configuration loading
Example migration:
# 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:
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 templatees_notification_text- Spanish notification text template
Language Detection and Fallback
The system automatically detects language preferences from:
- User Profile: Authenticated user's saved language preference
- Request Headers:
Accept-LanguageHTTP header - Default Fallback: English (
en)
Template Configuration
[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
-
Create language directory:
mkdir -p templates/email/fr_/html mkdir -p templates/email/fr_/text -
Add template files:
# Create French contact template touch templates/email/fr_/html/contact.hbs touch templates/email/fr_/text/contact.hbs -
Template variables:
{{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
# 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
.kfile - Simple syntax - encrypted values start with
@ - Automatic decryption during configuration loading
- CLI tools for managing encrypted values
- Environment variable compatibility alongside encryption
Quick Start
-
Generate Encryption Key:
cargo run --bin config_crypto_tool generate-key -
Encrypt Sensitive Values:
cargo run --bin config_crypto_tool encrypt "my_secret_password" # Output: @AbCdEf123456... -
Use in Configuration:
[session] secret = "@AbCdEf123456..." [database] url = "postgresql://user:@ZW5jcnlwdGVk@localhost:5432/db" -
Verify Setup:
cargo run --bin config_crypto_tool verify
Encryption Integration in Configuration
Configuration values starting with @ are automatically decrypted during loading:
# 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:
[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
- Environment variables (highest priority)
- Encrypted values (decrypted automatically)
- 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
- Encryption Key: A
.kfile in the project root contains the encryption key - Encrypted Values: Configuration values starting with
@are automatically decrypted - Automatic Management: The system handles key generation and value decryption seamlessly
Quick Start
# 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
# 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
# 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
- Never commit
.kfiles to version control - Use different keys for different environments
- Backup encryption keys securely
- Rotate keys regularly in production
- Monitor key file integrity
Mixed Configuration Approach
You can combine encrypted values with environment variables:
[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
# 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.