Files
attune/docs/configuration/configuration.md
2026-02-04 17:46:30 -06:00

14 KiB

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:

    cp config.example.yaml config.yaml
    
  2. Edit the configuration:

    nano config.yaml
    
  3. Set required values:

    • Database URL
    • JWT secret key
    • Encryption key
    • CORS origins (if applicable)
  4. Run the application:

    cargo run --bin attune-api
    

Configuration File Structure

Basic Example

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

service_name: attune      # Service identifier
environment: development  # Environment: development, test, staging, production

Database Configuration

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:

export ATTUNE__DATABASE__URL=postgresql://user:pass@localhost/attune
export ATTUNE__DATABASE__MAX_CONNECTIONS=100

Server Configuration

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:

export ATTUNE__SERVER__PORT=3000
export ATTUNE__SERVER__CORS_ORIGINS="https://app.com,https://www.app.com"

Security Configuration

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

export ATTUNE__SECURITY__JWT_SECRET=$(openssl rand -base64 64)
export ATTUNE__SECURITY__ENCRYPTION_KEY=$(openssl rand -base64 32)

Logging Configuration

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:

export ATTUNE__LOG__LEVEL=debug
export ATTUNE__LOG__FORMAT=pretty

Redis Configuration (Optional)

redis:
  url: redis://localhost:6379
  pool_size: 10

Message Queue Configuration (Optional)

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)

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:

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:

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:

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:

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__<section>__<key>=value

Examples

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

export ATTUNE_CONFIG=/path/to/custom-config.yaml
cargo run --bin attune-api

Or:

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:

config.yaml
config.*.yaml
!config.example.yaml
!config.development.yaml
!config.test.yaml

2. Use Strong Secrets

Generate cryptographically secure secrets:

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

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

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

docker run -v /path/to/config.yaml:/app/config.yaml attune-api
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

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

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

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

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:

    ls -la config.yaml
    
  2. Check YAML syntax:

    # Install yq if needed: brew install yq
    yq eval config.yaml
    
  3. Check environment variable:

    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:

    env | grep ATTUNE
    
  3. Check for typos:

    export ATTUNE__DATABASE__URL=...  # Correct
    export ATTUNE_DATABASE_URL=...     # Wrong! (single underscore)
    

Validation Errors

Enable debug logging to see detailed configuration:

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

ATTUNE__DATABASE__URL=postgresql://localhost/attune
ATTUNE__SERVER__PORT=8080
ATTUNE__LOG__LEVEL=info
ATTUNE__SECURITY__JWT_SECRET=my-secret

After (config.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