- 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>
10 KiB
Migration Guide: Environment Variables to TOML Configuration
This guide helps you migrate from the old environment variable-only configuration system to the new TOML-based configuration system with environment variable overrides.
Overview
The new configuration system provides:
- TOML files for structured configuration
- Environment variable overrides for sensitive data
- Environment-specific configs (dev, prod, etc.)
- Validation and error handling
- Better organization of settings
Migration Steps
Step 1: Identify Current Configuration
First, identify all environment variables currently used in your application:
# List all environment variables starting with common prefixes
env | grep -E "^(SERVER_|DATABASE_|SESSION_|CORS_|TLS_|OAUTH_|SMTP_|REDIS_|LOG_)" | sort
Step 2: Create Base Configuration File
Create a config.toml file with your current settings:
# config.toml
[server]
protocol = "http"
host = "127.0.0.1"
port = 3030
environment = "development"
log_level = "info"
[database]
url = "postgresql://localhost:5432/myapp"
max_connections = 10
min_connections = 1
connect_timeout = 30
idle_timeout = 600
max_lifetime = 1800
[session]
secret = "change-this-in-production"
cookie_name = "session_id"
cookie_secure = false
cookie_http_only = true
cookie_same_site = "lax"
max_age = 3600
[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]
enable_csrf = true
csrf_token_name = "csrf_token"
rate_limit_requests = 100
rate_limit_window = 60
bcrypt_cost = 12
[static]
assets_dir = "public"
site_root = "target/site"
site_pkg_dir = "pkg"
[oauth]
enabled = false
[email]
enabled = false
smtp_host = "localhost"
smtp_port = 587
smtp_username = ""
smtp_password = ""
from_email = "noreply@example.com"
from_name = "My App"
[redis]
enabled = false
url = "redis://localhost:6379"
pool_size = 10
connection_timeout = 5
command_timeout = 5
[app]
name = "My Rust App"
version = "0.1.0"
debug = true
enable_metrics = false
enable_health_check = true
enable_compression = true
max_request_size = 10485760
[logging]
format = "text"
level = "info"
file_path = "logs/app.log"
max_file_size = 10485760
max_files = 5
enable_console = true
enable_file = false
[content]
enabled = false
content_dir = "content"
cache_enabled = true
cache_ttl = 3600
max_file_size = 5242880
[features]
auth = true
tls = false
content_db = true
two_factor_auth = false
Step 3: Update Code to Use New Configuration
Replace the old configuration loading:
// OLD: Environment-only configuration
use config::ServerConfig;
let server_config = ServerConfig::from_env()?;
let addr = server_config.server_address();
let log_level = server_config.log_level;
With the new configuration system:
// NEW: TOML + Environment configuration
use config::Config;
let config = Config::load()?;
let addr = config.server_address();
let log_level = config.server.log_level;
Step 4: Environment Variable Mapping
Map your existing environment variables to the new system:
| Old Environment Variable | New TOML Location | Environment Override |
|---|---|---|
SERVER_HOST |
server.host |
SERVER_HOST |
SERVER_PORT |
server.port |
SERVER_PORT |
SERVER_PROTOCOL |
server.protocol |
SERVER_PROTOCOL |
DATABASE_URL |
database.url |
DATABASE_URL |
SESSION_SECRET |
session.secret |
SESSION_SECRET |
LOG_LEVEL |
server.log_level |
LOG_LEVEL |
ENVIRONMENT |
server.environment |
ENVIRONMENT |
TLS_CERT_PATH |
server.tls.cert_path |
TLS_CERT_PATH |
TLS_KEY_PATH |
server.tls.key_path |
TLS_KEY_PATH |
Step 5: Handle Sensitive Data
Move sensitive data to environment variables and use substitution:
# config.toml - Use environment variable substitution
[database]
url = "postgresql://user:${DATABASE_PASSWORD}@localhost:5432/myapp"
[session]
secret = "${SESSION_SECRET}"
[oauth.google]
client_id = "${GOOGLE_CLIENT_ID}"
client_secret = "${GOOGLE_CLIENT_SECRET}"
[email]
smtp_username = "${SMTP_USERNAME}"
smtp_password = "${SMTP_PASSWORD}"
Step 6: Create Environment-Specific Configurations
Create separate configuration files for different environments:
config.dev.toml:
[server]
protocol = "http"
host = "127.0.0.1"
port = 3030
environment = "development"
log_level = "debug"
[database]
url = "postgresql://dev:dev@localhost:5432/myapp_dev"
max_connections = 5
[security]
enable_csrf = false
rate_limit_requests = 1000
bcrypt_cost = 4
[session]
cookie_secure = false
max_age = 7200
config.prod.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://prod:${DATABASE_PASSWORD}@db.example.com:5432/myapp_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
Step 7: Update Deployment Scripts
Update your deployment scripts to use the new configuration system:
Docker:
# OLD
ENV SERVER_HOST=0.0.0.0
ENV SERVER_PORT=8080
ENV DATABASE_URL=postgresql://...
ENV SESSION_SECRET=...
# NEW
COPY config.prod.toml /app/config.toml
ENV ENVIRONMENT=production
ENV DATABASE_PASSWORD=...
ENV SESSION_SECRET=...
Kubernetes:
# OLD
env:
- name: SERVER_HOST
value: "0.0.0.0"
- name: SERVER_PORT
value: "8080"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
# NEW
env:
- name: ENVIRONMENT
value: "production"
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: database-password
- name: SESSION_SECRET
valueFrom:
secretKeyRef:
name: app-secrets
key: session-secret
Step 8: Update Environment Files
Update your .env files to work with the new system:
.env.development:
# Environment
ENVIRONMENT=development
# Database
DATABASE_URL=postgresql://dev:dev@localhost:5432/myapp_dev
# Session
SESSION_SECRET=dev-secret-not-for-production
# OAuth (optional)
GOOGLE_CLIENT_ID=your-dev-google-client-id
GOOGLE_CLIENT_SECRET=your-dev-google-client-secret
.env.production:
# Environment
ENVIRONMENT=production
# Database
DATABASE_PASSWORD=your-production-database-password
# Session
SESSION_SECRET=your-super-secret-production-key
# OAuth
GOOGLE_CLIENT_ID=your-production-google-client-id
GOOGLE_CLIENT_SECRET=your-production-google-client-secret
Step 9: Test the Migration
-
Validate configuration:
cargo run --bin config_tool -- validate -
Show current configuration:
cargo run --bin config_tool -- show -
Check environment variables:
cargo run --bin config_tool -- check-env -
Run your application:
cargo run
Step 10: Update Documentation
Update your project documentation to reflect the new configuration system:
- Update README.md with configuration instructions
- Document required environment variables
- Provide example configuration files
- Update deployment guides
Common Migration Issues
Issue 1: Configuration Not Found
Error:
Configuration file not found: config.toml
Solution:
Create a configuration file or set the CONFIG_FILE environment variable:
cp config.dev.toml config.toml
# or
export CONFIG_FILE=/path/to/your/config.toml
Issue 2: Environment Variable Substitution
Error:
Environment variable 'DATABASE_PASSWORD' not found
Solution: Set the required environment variable:
export DATABASE_PASSWORD=your-password
Issue 3: TLS Configuration
Error:
TLS certificate path is required when using HTTPS
Solution: Either disable HTTPS or provide certificate paths:
[server]
protocol = "http" # Disable HTTPS
# or
protocol = "https"
[server.tls]
cert_path = "/path/to/cert.crt"
key_path = "/path/to/key.key"
Issue 4: Database Connection
Error:
Failed to connect to database
Solution: Check your database URL format and ensure the database is running:
[database]
url = "postgresql://username:password@host:port/database"
Migration Checklist
- Identify all current environment variables
- Create base
config.tomlfile - Update code to use
Config::load() - Create environment-specific config files
- Move sensitive data to environment variables
- Update deployment scripts
- Update
.envfiles - Test configuration loading
- Validate configuration
- Update documentation
- Update CI/CD pipelines
- Train team on new configuration system
Rollback Plan
If you need to rollback to the old system:
- Keep the old configuration loading code in a separate branch
- Maintain both systems during transition period
- Use feature flags to switch between systems
- Document the rollback process
// Rollback configuration loading
#[cfg(feature = "legacy-config")]
let config = ServerConfig::from_env()?;
#[cfg(not(feature = "legacy-config"))]
let config = Config::load()?;
Best Practices After Migration
- Version control: Keep configuration files in version control (except sensitive production configs)
- Environment parity: Ensure dev/staging/prod configurations are consistent
- Documentation: Keep configuration documentation up to date
- Validation: Regularly validate configuration files
- Secrets management: Use proper secrets management for production
- Monitoring: Monitor configuration changes in production
- Testing: Test configuration loading in CI/CD
- Backup: Backup configuration files regularly
Getting Help
If you encounter issues during migration:
- Run the configuration tool:
cargo run --bin config_tool -- help - Check the configuration examples in the repository
- Review the CONFIG_README.md for detailed documentation
- Open an issue on the project repository