# 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:

```bash
# 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:

```toml
# 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:

```rust
// 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:

```rust
// 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:

```toml
# 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:**
```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:**
```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:**
```dockerfile
# 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:**
```yaml
# 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:**
```bash
# 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:**
```bash
# 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

1. **Validate configuration:**
   ```bash
   cargo run --bin config_tool -- validate
   ```

2. **Show current configuration:**
   ```bash
   cargo run --bin config_tool -- show
   ```

3. **Check environment variables:**
   ```bash
   cargo run --bin config_tool -- check-env
   ```

4. **Run your application:**
   ```bash
   cargo run
   ```

### Step 10: Update Documentation

Update your project documentation to reflect the new configuration system:

1. Update README.md with configuration instructions
2. Document required environment variables
3. Provide example configuration files
4. 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:
```bash
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:
```bash
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:
```toml
[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:
```toml
[database]
url = "postgresql://username:password@host:port/database"
```

## Migration Checklist

- [ ] Identify all current environment variables
- [ ] Create base `config.toml` file
- [ ] Update code to use `Config::load()`
- [ ] Create environment-specific config files
- [ ] Move sensitive data to environment variables
- [ ] Update deployment scripts
- [ ] Update `.env` files
- [ ] 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:

1. Keep the old configuration loading code in a separate branch
2. Maintain both systems during transition period
3. Use feature flags to switch between systems
4. Document the rollback process

```rust
// 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

1. **Version control:** Keep configuration files in version control (except sensitive production configs)
2. **Environment parity:** Ensure dev/staging/prod configurations are consistent
3. **Documentation:** Keep configuration documentation up to date
4. **Validation:** Regularly validate configuration files
5. **Secrets management:** Use proper secrets management for production
6. **Monitoring:** Monitor configuration changes in production
7. **Testing:** Test configuration loading in CI/CD
8. **Backup:** Backup configuration files regularly

## Getting Help

If you encounter issues during migration:

1. Run the configuration tool: `cargo run --bin config_tool -- help`
2. Check the configuration examples in the repository
3. Review the CONFIG_README.md for detailed documentation
4. Open an issue on the project repository