| name | terraform |
| description | Terraform Infrastructure as Code best practices |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"developers","category":"devops"} |
What I do
- Write Terraform configurations for cloud infrastructure
- Manage state files and backends
- Use modules for reusable infrastructure
- Implement remote state with locking
- Handle secrets with Vault or cloud providers
- Use workspaces for environment management
- Implement CI/CD for Terraform
- Follow security best practices
When to use me
When creating Terraform configurations or managing cloud infrastructure.
Terraform Structure
terraform/
├── environments/
│ ├── prod/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ └── ...
│ └── dev/
│ └── ...
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/
│ │ └── ...
│ └── database/
│ └── ...
└── global/
└── s3/
└── ...
Main Configuration
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
# Remote state with locking
backend "s3" {
bucket = "my-terraform-state"
key = "environments/prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "terraform"
Project = var.project_name
}
}
}
# Variables
variable "aws_region" {
description = "AWS region"
type = string
default = "us-east-1"
}
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "vpc_cidr" {
description = "VPC CIDR block"
type = string
default = "10.0.0.0/16"
}
# Use workspaces for environment separation
# terraform workspace new prod
# terraform workspace select prod
VPC Module
# modules/networking/main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-igw"
}
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-${count.index + 1}"
}
}
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
tags = {
Name = "${var.environment}-private-${count.index + 1}"
}
}
resource "aws_nat_gateway" "main" {
count = length(var.public_subnet_cidrs)
subnet_id = aws_subnet.public[count.index].id
allocation_id = aws_eip.nat[count.index].id
tags = {
Name = "${var.environment}-nat-${count.index + 1}"
}
}
resource "aws_eip" "nat" {
count = length(var.public_subnet_cidrs)
vpc = true
}
EC2 and Auto Scaling
resource "aws_launch_template" "app" {
name_prefix = "${var.environment}-app"
image_id = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
key_name = var.ssh_key_name
vpc_security_group_ids = [aws_security_group.app.id]
user_data = base64encode(templatefile("${path.module}/user-data.sh", {
environment = var.environment
api_key = var.api_key
}))
iam_instance_profile {
name = aws_iam_instance_profile.app.name
}
tag_specifications {
resource_type = "instance"
tags = {
Name = "${var.environment}-app"
Environment = var.environment
}
}
}
resource "aws_autoscaling_group" "app" {
name = "${var.environment}-app-asg"
vpc_zone_identifier = module.vpc.private_subnet_ids
target_group_arns = [aws_lb_target_group.app.arn]
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
min_size = var.min_size
max_size = var.max_size
desired_capacity = var.desired_capacity
health_check_type = "ELB"
health_check_grace_period = 300
lifecycle {
create_before_destroy = true
}
tag {
key = "Name"
value = "${var.environment}-app"
propagate_at_launch = true
}
}
Terraform Workflow
terraform init
terraform plan -var-file="environments/prod/terraform.tfvars"
terraform apply -var-file="environments/prod/terraform.tfvars"
terraform fmt -recursive
terraform validate
terraform plan -detailed-exitcode
terraform state list
terraform state mv aws_instance.old aws_instance.new
terraform state rm aws_instance.deprecated
terraform workspace list
terraform workspace new staging
terraform workspace select prod
terraform import aws_instance.existing i-1234567890abcdef0
terraform destroy -var-file="environments/dev/terraform.tfvars"