Terraform Overview
This section covers using Terraform to provision AWS infrastructure for Rack Gateway, including RDS, S3 WORM buckets, KMS keys, and networking.
Why Terraform?
Section titled “Why Terraform?”Managing Rack Gateway infrastructure with Terraform provides:
- Reproducibility - Same infrastructure across environments
- Version control - Track infrastructure changes in git
- Automation - CI/CD for infrastructure deployments
- Documentation - Code is documentation
Infrastructure Components
Section titled “Infrastructure Components” AWS Infrastructure VPC, RDS, security groups, and IAM.
S3 WORM Storage Immutable audit log anchoring.
Multi-Region Deploy across multiple regions.
Architecture Overview
Section titled “Architecture Overview”Module Structure
Section titled “Module Structure”terraform/├── modules/│ ├── rack_gateway/ # Main gateway module│ │ ├── main.tf # RDS, S3, KMS resources│ │ ├── variables.tf # Input variables│ │ ├── outputs.tf # Output values│ │ └── iam.tf # IAM roles and policies│ └── networking/ # VPC and subnets│ ├── main.tf│ └── variables.tf├── environments/│ ├── staging/│ │ ├── main.tf # Staging configuration│ │ └── terraform.tfvars # Staging values│ └── production/│ ├── main.tf # Production configuration│ └── terraform.tfvars # Production values└── global/ └── shared/ # Cross-environment resourcesQuick Start
Section titled “Quick Start”-
Initialize Terraform
Terminal window cd terraform/environments/productionterraform init -
Review the plan
Terminal window terraform plan -out=plan.tfplan -
Apply changes
Terminal window terraform apply plan.tfplan -
Retrieve outputs
Terminal window terraform output database_urlterraform output audit_anchor_bucket
Minimal Configuration
Section titled “Minimal Configuration”module "rack_gateway" { source = "../../modules/rack_gateway"
environment = "production" vpc_id = var.vpc_id subnet_ids = var.private_subnet_ids
# Database db_instance_class = "db.t3.medium" db_password = var.db_password
# S3 WORM enable_audit_anchoring = true worm_retention_days = 400
# Tags tags = { Environment = "production" Project = "rack-gateway" }}Module Reference
Section titled “Module Reference”rack_gateway Module
Section titled “rack_gateway Module”| Variable | Type | Required | Description |
|---|---|---|---|
environment | string | Yes | Environment name (staging, production) |
vpc_id | string | Yes | VPC ID for resources |
subnet_ids | list | Yes | Private subnet IDs |
db_instance_class | string | No | RDS instance type (default: db.t3.small) |
db_password | string | Yes | Database password (sensitive) |
enable_audit_anchoring | bool | No | Enable S3 WORM bucket (default: true) |
worm_retention_days | number | No | Object Lock retention (default: 400) |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
database_url | PostgreSQL connection string |
database_host | RDS endpoint hostname |
audit_anchor_bucket | S3 bucket name for anchors |
kms_key_arn | KMS key ARN for encryption |
iam_role_arn | IAM role for S3 access |
State Management
Section titled “State Management”Remote State (Recommended)
Section titled “Remote State (Recommended)”Store Terraform state in S3 with locking:
terraform { backend "s3" { bucket = "myorg-terraform-state" key = "rack-gateway/production/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" }}State Locking
Section titled “State Locking”Create the DynamoDB table for state locking:
resource "aws_dynamodb_table" "terraform_locks" { name = "terraform-locks" billing_mode = "PAY_PER_REQUEST" hash_key = "LockID"
attribute { name = "LockID" type = "S" }}Security Considerations
Section titled “Security Considerations”Sensitive Variables
Section titled “Sensitive Variables”Never commit secrets to git. Use:
- Terraform Cloud/Enterprise variables
- AWS Secrets Manager
- Environment variables
# terraform.tfvars (add to .gitignore)db_password = "secure-password-here"Or use environment variables:
export TF_VAR_db_password="secure-password-here"terraform applyIAM Permissions
Section titled “IAM Permissions”Terraform needs these AWS permissions:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "rds:*", "s3:*", "kms:*", "iam:*", "ec2:Describe*", "ec2:CreateSecurityGroup", "ec2:DeleteSecurityGroup", "ec2:AuthorizeSecurityGroupIngress", "ec2:RevokeSecurityGroupIngress" ], "Resource": "*" } ]}CI/CD Integration
Section titled “CI/CD Integration”GitHub Actions
Section titled “GitHub Actions”name: Terraform
on: push: branches: [main] paths: ['terraform/**'] pull_request: paths: ['terraform/**']
jobs: terraform: runs-on: ubuntu-latest defaults: run: working-directory: terraform/environments/production
steps: - uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.6
- name: Terraform Init run: terraform init
- name: Terraform Plan run: terraform plan -no-color env: TF_VAR_db_password: ${{ secrets.DB_PASSWORD }}
- name: Terraform Apply if: github.ref == 'refs/heads/main' run: terraform apply -auto-approve env: TF_VAR_db_password: ${{ secrets.DB_PASSWORD }}Importing Existing Resources
Section titled “Importing Existing Resources”If you have existing infrastructure:
# Import existing RDS instanceterraform import module.rack_gateway.aws_db_instance.main rack-gateway
# Import existing S3 bucketterraform import module.rack_gateway.aws_s3_bucket.audit_anchors audit-anchors-prodTroubleshooting
Section titled “Troubleshooting”State Issues
Section titled “State Issues”# List state resourcesterraform state list
# Show resource detailsterraform state show module.rack_gateway.aws_db_instance.main
# Remove resource from state (careful!)terraform state rm module.rack_gateway.aws_db_instance.mainPlan Diffs
Section titled “Plan Diffs”If Terraform shows unexpected changes:
- Check for manual changes in AWS console
- Verify variable values match current state
- Run
terraform refreshto sync state
Resource Dependencies
Section titled “Resource Dependencies”If resources fail to create in order:
# Explicit dependencyresource "aws_db_instance" "main" { depends_on = [aws_security_group.rds] # ...}Best Practices
Section titled “Best Practices”Environment Isolation
Section titled “Environment Isolation”- Separate state files per environment
- Different AWS accounts for prod/non-prod
- Consistent naming conventions
Change Management
Section titled “Change Management”- Always review plans before applying
- Use workspaces or directories for environments
- Tag resources for cost tracking
Documentation
Section titled “Documentation”- Document module inputs/outputs
- Include architecture diagrams
- Maintain runbooks for common operations
Next Steps
Section titled “Next Steps”- AWS Infrastructure - VPC, RDS, IAM setup
- S3 WORM Storage - Audit anchoring
- Multi-Region - Cross-region deployment