# Production Deployment Guide This document provides guidelines and checklists for deploying Attune to production environments. ## Table of Contents - [Pre-Deployment Checklist](#pre-deployment-checklist) - [Database Configuration](#database-configuration) - [Environment Variables](#environment-variables) - [Schema Verification](#schema-verification) - [Security Best Practices](#security-best-practices) - [Deployment Steps](#deployment-steps) - [Post-Deployment Validation](#post-deployment-validation) - [Troubleshooting](#troubleshooting) --- ## Pre-Deployment Checklist Before deploying Attune to production, verify the following: - [ ] PostgreSQL 14+ database is provisioned and accessible - [ ] RabbitMQ 3.12+ message queue is configured - [ ] All required environment variables are set (see below) - [ ] Database migrations have been tested in staging - [ ] SSL/TLS certificates are configured for HTTPS - [ ] Log aggregation and monitoring are configured - [ ] Backup and disaster recovery procedures are in place - [ ] Security audit has been completed - [ ] Load balancing and high availability are configured (if applicable) --- ## Environment Variables ### Required Variables These environment variables **MUST** be set before deploying: ```bash # Database connection (required) export DATABASE_URL="postgresql://username:password@host:port/database" # JWT secret for authentication (required, 64+ characters) # Generate with: openssl rand -base64 64 export JWT_SECRET="your-secure-jwt-secret-here" # Encryption key for secrets storage (required, 32+ characters) # Generate with: openssl rand -base64 32 export ENCRYPTION_KEY="your-secure-encryption-key-here" ``` ### Optional Variables ```bash # Redis (for caching) export REDIS_URL="redis://host:6379" # RabbitMQ (for message queue) export RABBITMQ_URL="amqp://user:pass@host:5672/%2f" # CORS origins (comma-separated) export ATTUNE__SERVER__CORS_ORIGINS="https://app.example.com,https://www.example.com" # Log level override export ATTUNE__LOG__LEVEL="info" # Server port override export ATTUNE__SERVER__PORT="8080" # Schema override (should always be 'attune' in production) export ATTUNE__DATABASE__SCHEMA="attune" ``` ### Environment Variable Format Attune uses hierarchical configuration with the prefix `ATTUNE__` and separator `__`: - `ATTUNE__DATABASE__URL` → `database.url` - `ATTUNE__SERVER__PORT` → `server.port` - `ATTUNE__LOG__LEVEL` → `log.level` --- ## Schema Verification ### Automatic Verification Attune includes built-in schema validation: 1. **Schema Name Validation**: Only alphanumeric and underscores allowed (max 63 chars) 2. **SQL Injection Prevention**: Schema names are validated before use 3. **Logging**: Production schema usage is logged prominently at startup ### Manual Verification Script Run this verification before deployment: ```bash # Verify configuration loads correctly cargo run --release --bin attune-api -- --config config.production.yaml --dry-run # Check logs for schema confirmation cargo run --release --bin attune-api 2>&1 | grep -i schema ``` Expected output: ``` INFO Using production schema: attune INFO Connecting to database with max_connections=20, schema=attune ``` ### Database Schema Check After deployment, verify the schema in the database: ```bash # Connect to your production database psql $DATABASE_URL # Verify schema exists \dn attune # Verify search_path includes attune SHOW search_path; # Verify tables are in attune schema SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'attune' ORDER BY tablename; ``` You should see all 17 Attune tables: - `action` - `enforcement` - `event` - `execution` - `execution_log` - `identity` - `inquiry` - `inquiry_response` - `key` - `pack` - `rule` - `rule_enforcement` - `sensor` - `sensor_instance` - `trigger` - `trigger_instance` - `workflow_definition` --- ## Security Best Practices ### Secrets Management 1. **Never commit secrets to version control** 2. **Use environment variables or secret management systems** (e.g., AWS Secrets Manager, HashiCorp Vault) 3. **Rotate secrets regularly** (JWT secret, encryption key, database passwords) 4. **Use strong, randomly generated secrets** (use provided generation commands) ### Database Security 1. **Use dedicated database user** with minimal required permissions 2. **Enable SSL/TLS** for database connections 3. **Use connection pooling** (configured via `max_connections`) 4. **Restrict network access** to database (firewall rules, VPC, etc.) 5. **Enable audit logging** for sensitive operations ### Application Security 1. **Run as non-root user** in containers/VMs 2. **Enable HTTPS** for all API endpoints (use reverse proxy like nginx) 3. **Configure CORS properly** (only allow trusted origins) 4. **Set up rate limiting** and DDoS protection 5. **Enable security headers** (CSP, HSTS, X-Frame-Options, etc.) 6. **Keep dependencies updated** (run `cargo audit` regularly) --- ## Deployment Steps ### 1. Prepare Database ```bash # Create production database (if not exists) createdb -h your-db-host -U your-db-user attune_prod # Run migrations export DATABASE_URL="postgresql://user:pass@host:port/attune_prod" export ATTUNE__DATABASE__SCHEMA="attune" sqlx migrate run --source ./migrations ``` ### 2. Build Application ```bash # Build release binary cargo build --release --bin attune-api # Or build Docker image docker build -t attune-api:latest -f docker/api.Dockerfile . ``` ### 3. Configure Environment ```bash # Set all required environment variables export DATABASE_URL="postgresql://..." export JWT_SECRET="$(openssl rand -base64 64)" export ENCRYPTION_KEY="$(openssl rand -base64 32)" export ATTUNE__DATABASE__SCHEMA="attune" # ... etc ``` ### 4. Deploy Services ```bash # Start API service ./target/release/attune-api --config config.production.yaml # Or with Docker docker run -d \ --name attune-api \ -p 8080:8080 \ -e DATABASE_URL="$DATABASE_URL" \ -e JWT_SECRET="$JWT_SECRET" \ -e ENCRYPTION_KEY="$ENCRYPTION_KEY" \ -v ./config.production.yaml:/app/config.production.yaml \ attune-api:latest ``` ### 5. Load Core Pack ```bash # Load the core pack (provides essential actions and sensors) ./scripts/load-core-pack.sh ``` --- ## Post-Deployment Validation ### Health Check ```bash # Check API health endpoint curl http://your-api-host:8080/health # Expected response: # {"status":"ok","timestamp":"2024-01-15T12:00:00Z"} ``` ### Schema Validation ```bash # Check application logs for schema confirmation docker logs attune-api 2>&1 | grep -i schema # Expected output: # INFO Using production schema: attune ``` ### Functional Tests ```bash # Test authentication curl -X POST http://your-api-host:8080/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"your-password"}' # Test pack listing curl http://your-api-host:8080/api/v1/packs \ -H "Authorization: Bearer YOUR_TOKEN" # Test action execution curl -X POST http://your-api-host:8080/api/v1/executions \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"action_ref":"core.echo","parameters":{"message":"Hello"}}' ``` ### Monitoring Set up monitoring for: - **Application health**: `/health` endpoint availability - **Database connections**: Pool size and connection errors - **Error rates**: 4xx and 5xx HTTP responses - **Response times**: P50, P95, P99 latencies - **Resource usage**: CPU, memory, disk, network - **Schema usage**: Verify `attune` schema in logs --- ## Troubleshooting ### Issue: Schema Not Found **Symptoms:** - Application startup fails with "schema does not exist" - Database queries fail with "schema not found" **Solution:** 1. Verify schema exists: `psql $DATABASE_URL -c "\dn attune"` 2. If missing, run migrations: `sqlx migrate run --source ./migrations` 3. Check migration files uncommented schema creation (first migration) ### Issue: Connection Pool Exhausted **Symptoms:** - Timeout errors - "connection pool exhausted" errors - Slow response times **Solution:** 1. Increase `max_connections` in config 2. Check for connection leaks in application logs 3. Verify database can handle the connection load 4. Consider scaling horizontally (multiple instances) ### Issue: Authentication Fails **Symptoms:** - All requests return 401 Unauthorized - Token validation errors in logs **Solution:** 1. Verify `JWT_SECRET` is set correctly 2. Check token expiration times in config 3. Ensure clocks are synchronized (NTP) 4. Verify `enable_auth: true` in config ### Issue: Migrations Fail **Symptoms:** - `sqlx migrate run` errors - "relation already exists" or "schema already exists" **Solution:** 1. Check `_sqlx_migrations` table: `SELECT * FROM attune._sqlx_migrations;` 2. Verify migrations are in correct order 3. For fresh deployment, drop and recreate schema if safe 4. Check PostgreSQL version compatibility (requires 14+) --- ## Rollback Procedure If issues occur after deployment: 1. **Stop the application**: `systemctl stop attune-api` (or equivalent) 2. **Revert to previous version**: Deploy previous known-good version 3. **Restore database backup** (if migrations were run): ```bash pg_restore -d attune_prod backup.dump ``` 4. **Verify old version works**: Run post-deployment validation steps 5. **Investigate issue**: Review logs, error messages, configuration changes --- ## Additional Resources - [Configuration Guide](./configuration.md) - [Schema-Per-Test Architecture](./schema-per-test.md) - [API Documentation](./api-overview.md) - [Security Best Practices](./security.md) - [Monitoring and Observability](./monitoring.md) --- ## Support For production issues or questions: - GitHub Issues: https://github.com/your-org/attune/issues - Documentation: https://docs.attune.example.com - Community: https://community.attune.example.com