# Configuration Guide This guide explains how to configure the Attune automation platform using YAML configuration files. ## Overview Attune uses a layered configuration system with YAML files as the primary configuration source. Configuration can be overridden using environment variables, making it flexible for different deployment scenarios. ## Configuration Loading Priority Configuration is loaded in the following order (later sources override earlier ones): 1. **Base configuration file** (`config.yaml` or path from `ATTUNE_CONFIG` environment variable) 2. **Environment-specific configuration** (e.g., `config.development.yaml`, `config.production.yaml`) 3. **Environment variables** (prefix: `ATTUNE__`, separator: `__`) This layered approach allows you to: - Keep common settings in `config.yaml` - Override settings per environment (dev, test, production) - Override sensitive values with environment variables (recommended for production) ## Quick Start 1. **Copy the example configuration:** ```bash cp config.example.yaml config.yaml ``` 2. **Edit the configuration:** ```bash nano config.yaml ``` 3. **Set required values:** - Database URL - JWT secret key - Encryption key - CORS origins (if applicable) 4. **Run the application:** ```bash cargo run --bin attune-api ``` ## Configuration File Structure ### Basic Example ```yaml service_name: attune environment: development database: url: postgresql://postgres:postgres@localhost:5432/attune max_connections: 50 server: host: 0.0.0.0 port: 8080 cors_origins: - http://localhost:3000 security: jwt_secret: your-secret-key-here jwt_access_expiration: 3600 log: level: info format: json ``` ## Configuration Sections ### Service Metadata ```yaml service_name: attune # Service identifier environment: development # Environment: development, test, staging, production ``` ### Database Configuration ```yaml database: # PostgreSQL connection URL url: postgresql://username:password@host:port/database # Connection pool settings max_connections: 50 # Maximum pool size min_connections: 5 # Minimum pool size connect_timeout: 30 # Connection timeout (seconds) idle_timeout: 600 # Idle connection timeout (seconds) # Debugging log_statements: false # Log SQL statements (set true for debugging) ``` **Environment variable override:** ```bash export ATTUNE__DATABASE__URL=postgresql://user:pass@localhost/attune export ATTUNE__DATABASE__MAX_CONNECTIONS=100 ``` ### Server Configuration ```yaml server: host: 0.0.0.0 # Bind address (0.0.0.0 for all interfaces) port: 8080 # HTTP port request_timeout: 30 # Request timeout (seconds) enable_cors: true # Enable CORS middleware # Allowed CORS origins cors_origins: - http://localhost:3000 - https://app.example.com max_body_size: 10485760 # Max request body size (10MB in bytes) ``` **Environment variable override:** ```bash export ATTUNE__SERVER__PORT=3000 export ATTUNE__SERVER__CORS_ORIGINS="https://app.com,https://www.app.com" ``` ### Security Configuration ```yaml security: # JWT secret for signing tokens (REQUIRED if enable_auth is true) # Generate with: openssl rand -base64 64 jwt_secret: your-secret-key-here # Token expiration times (seconds) jwt_access_expiration: 3600 # Access token: 1 hour jwt_refresh_expiration: 604800 # Refresh token: 7 days # Encryption key for storing secrets (must be at least 32 characters) # Generate with: openssl rand -base64 32 encryption_key: your-32-char-encryption-key-here # Enable/disable authentication enable_auth: true ``` **Environment variable override (recommended for production):** ```bash export ATTUNE__SECURITY__JWT_SECRET=$(openssl rand -base64 64) export ATTUNE__SECURITY__ENCRYPTION_KEY=$(openssl rand -base64 32) ``` ### Logging Configuration ```yaml log: # Log level: trace, debug, info, warn, error level: info # Log format: json (structured), pretty (human-readable) format: json # Enable console output console: true # Optional: write logs to file file: /var/log/attune/attune.log ``` **Environment variable override:** ```bash export ATTUNE__LOG__LEVEL=debug export ATTUNE__LOG__FORMAT=pretty ``` ### Redis Configuration (Optional) ```yaml redis: url: redis://localhost:6379 pool_size: 10 ``` ### Message Queue Configuration (Optional) ```yaml message_queue: url: amqp://guest:guest@localhost:5672/%2f exchange: attune enable_dlq: true # Enable dead letter queue message_ttl: 3600 # Message TTL (seconds) ``` ### Worker Configuration (Optional) ```yaml worker: name: attune-worker-1 worker_type: local # local, remote, container max_concurrent_tasks: 10 heartbeat_interval: 30 # seconds task_timeout: 300 # seconds ``` ## Environment-Specific Configuration ### Development Environment Create `config.development.yaml`: ```yaml environment: development database: url: postgresql://postgres:postgres@localhost:5432/attune log_statements: true server: host: 127.0.0.1 cors_origins: - http://localhost:3000 - http://localhost:5173 log: level: debug format: pretty security: jwt_secret: dev-secret-not-for-production jwt_access_expiration: 86400 # 24 hours for dev convenience ``` ### Production Environment Create `config.production.yaml`: ```yaml environment: production database: url: postgresql://attune_user:CHANGE_ME@db.example.com/attune max_connections: 100 log_statements: false server: cors_origins: - https://app.example.com - https://www.example.com log: level: info format: json file: /var/log/attune/attune.log security: # Override with environment variables! jwt_secret: CHANGE_ME_USE_ENV_VAR encryption_key: CHANGE_ME_USE_ENV_VAR ``` **Important:** Always override sensitive values in production using environment variables: ```bash export ATTUNE__SECURITY__JWT_SECRET=$(openssl rand -base64 64) export ATTUNE__SECURITY__ENCRYPTION_KEY=$(openssl rand -base64 32) export ATTUNE__DATABASE__URL=postgresql://user:pass@db.example.com/attune ``` ### Test Environment Create `config.test.yaml`: ```yaml environment: test database: url: postgresql://postgres:postgres@localhost:5432/attune_test max_connections: 10 server: port: 0 # Random port for tests log: level: warn format: pretty security: jwt_secret: test-secret-not-secure jwt_access_expiration: 300 # 5 minutes ``` ## Environment Variables You can override any configuration value using environment variables with the `ATTUNE__` prefix and `__` separator for nested keys. ### Syntax ``` ATTUNE__
__=value ``` ### Examples ```bash # Database export ATTUNE__DATABASE__URL=postgresql://localhost/attune export ATTUNE__DATABASE__MAX_CONNECTIONS=100 # Server export ATTUNE__SERVER__PORT=8080 export ATTUNE__SERVER__HOST=0.0.0.0 # Security export ATTUNE__SECURITY__JWT_SECRET=my-secret-key export ATTUNE__SECURITY__ENABLE_AUTH=true # Logging export ATTUNE__LOG__LEVEL=debug export ATTUNE__LOG__FORMAT=pretty # Arrays (comma-separated) export ATTUNE__SERVER__CORS_ORIGINS="https://app.com,https://www.app.com" ``` ### Boolean Values Boolean values can be set using: - `true`, `1`, `yes`, `on` → true - `false`, `0`, `no`, `off` → false ```bash export ATTUNE__DATABASE__LOG_STATEMENTS=true export ATTUNE__SECURITY__ENABLE_AUTH=false ``` ## Custom Configuration File Path By default, Attune looks for `config.yaml` in the current directory. You can specify a custom path: ```bash export ATTUNE_CONFIG=/path/to/custom-config.yaml cargo run --bin attune-api ``` Or: ```bash ATTUNE_CONFIG=/etc/attune/config.yaml attune-api ``` ## Configuration Validation The application validates configuration on startup and will fail with clear error messages if: - Required fields are missing (e.g., JWT secret when auth is enabled) - Values are invalid (e.g., invalid log level) - Security requirements are not met (e.g., encryption key too short) Example validation errors: ``` Error: Configuration validation failed: JWT secret is required when authentication is enabled Error: Invalid log level: trace. Must be one of: ["trace", "debug", "info", "warn", "error"] Error: Encryption key must be at least 32 characters ``` ## Security Best Practices ### 1. Never Commit Secrets Add sensitive config files to `.gitignore`: ```gitignore config.yaml config.*.yaml !config.example.yaml !config.development.yaml !config.test.yaml ``` ### 2. Use Strong Secrets Generate cryptographically secure secrets: ```bash # JWT secret (64 bytes, base64 encoded) openssl rand -base64 64 # Encryption key (32 bytes minimum, base64 encoded) openssl rand -base64 32 ``` ### 3. Environment Variables in Production Always use environment variables for sensitive values in production: ```bash # In production deployment export ATTUNE__SECURITY__JWT_SECRET=$(openssl rand -base64 64) export ATTUNE__SECURITY__ENCRYPTION_KEY=$(openssl rand -base64 32) export ATTUNE__DATABASE__URL=postgresql://user:${DB_PASSWORD}@db.example.com/attune ``` ### 4. File Permissions Restrict access to configuration files: ```bash chmod 600 config.yaml chown appuser:appuser config.yaml ``` ### 5. Separate Configs Per Environment Use environment-specific files and never share production secrets with development: ``` config.yaml # Base (committed) config.example.yaml # Example (committed) config.development.yaml # Development (committed, no real secrets) config.production.yaml # Production template (committed, placeholders only) config.yaml # Actual config (NOT committed, local overrides) ``` ## Docker/Container Deployments ### Option 1: Mount Configuration File ```bash docker run -v /path/to/config.yaml:/app/config.yaml attune-api ``` ### Option 2: Environment Variables (Recommended) ```bash docker run \ -e ATTUNE__DATABASE__URL=postgresql://db/attune \ -e ATTUNE__SECURITY__JWT_SECRET=$(cat /run/secrets/jwt_secret) \ -e ATTUNE__SERVER__PORT=8080 \ attune-api ``` ### Docker Compose Example ```yaml version: '3.8' services: api: image: attune-api environment: ATTUNE__DATABASE__URL: postgresql://postgres:postgres@db:5432/attune ATTUNE__SERVER__PORT: 8080 ATTUNE__LOG__LEVEL: info secrets: - jwt_secret - encryption_key command: sh -c " export ATTUNE__SECURITY__JWT_SECRET=$$(cat /run/secrets/jwt_secret) && export ATTUNE__SECURITY__ENCRYPTION_KEY=$$(cat /run/secrets/encryption_key) && attune-api " secrets: jwt_secret: file: ./secrets/jwt_secret.txt encryption_key: file: ./secrets/encryption_key.txt ``` ## Kubernetes Deployments ### ConfigMap for Base Configuration ```yaml apiVersion: v1 kind: ConfigMap metadata: name: attune-config data: config.yaml: | service_name: attune environment: production server: host: 0.0.0.0 port: 8080 log: level: info format: json ``` ### Secrets for Sensitive Values ```yaml apiVersion: v1 kind: Secret metadata: name: attune-secrets type: Opaque stringData: jwt-secret: "your-base64-jwt-secret" encryption-key: "your-base64-encryption-key" database-url: "postgresql://user:pass@db/attune" ``` ### Deployment ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: attune-api spec: template: spec: containers: - name: api image: attune-api:latest env: - name: ATTUNE__SECURITY__JWT_SECRET valueFrom: secretKeyRef: name: attune-secrets key: jwt-secret - name: ATTUNE__SECURITY__ENCRYPTION_KEY valueFrom: secretKeyRef: name: attune-secrets key: encryption-key - name: ATTUNE__DATABASE__URL valueFrom: secretKeyRef: name: attune-secrets key: database-url volumeMounts: - name: config mountPath: /app/config.yaml subPath: config.yaml volumes: - name: config configMap: name: attune-config ``` ## Troubleshooting ### Configuration Not Loading 1. **Check file exists:** ```bash ls -la config.yaml ``` 2. **Check YAML syntax:** ```bash # Install yq if needed: brew install yq yq eval config.yaml ``` 3. **Check environment variable:** ```bash echo $ATTUNE_CONFIG ``` ### Environment Variables Not Working 1. **Check variable name format:** - Must start with `ATTUNE__` - Use double underscores for nesting - Case-sensitive 2. **Verify variable is set:** ```bash env | grep ATTUNE ``` 3. **Check for typos:** ```bash export ATTUNE__DATABASE__URL=... # Correct export ATTUNE_DATABASE_URL=... # Wrong! (single underscore) ``` ### Validation Errors Enable debug logging to see detailed configuration: ```bash ATTUNE__LOG__LEVEL=debug cargo run --bin attune-api ``` ## Migration from .env Files If you're migrating from `.env` files, here's a conversion guide: ### Before (.env): ```bash ATTUNE__DATABASE__URL=postgresql://localhost/attune ATTUNE__SERVER__PORT=8080 ATTUNE__LOG__LEVEL=info ATTUNE__SECURITY__JWT_SECRET=my-secret ``` ### After (config.yaml): ```yaml database: url: postgresql://localhost/attune server: port: 8080 log: level: info security: jwt_secret: my-secret ``` **Note:** You can still use environment variables for overrides, but the base configuration is now in YAML. ## Additional Resources - [Quick Start Guide](quick-start.md) - [Authentication Documentation](authentication.md) - [API Reference](api-reference.md) - [Deployment Guide](deployment.md)