Terraform
Infrastructure as Code for complete control
šµ Cost: Terraform itself is FREE and open source. However, the AWS resources it creates will incur charges. Always run terraform plan to review what will be created before terraform apply. Use terraform destroy to remove all resources and stop charges. See our Costs & Cleanup Guide.
What is Terraform?
Terraform is an Infrastructure as Code (IaC) tool that lets you define cloud resources in declarative configuration files. You describe what you want, and Terraform figures out how to create it.
Declarative vs Imperative
Why Terraform?
- Version Control: Track infrastructure changes in Git
- Reproducibility: Create identical environments from same code
- Multi-Cloud: Same language for AWS, GCP, Azure
- State Management: Knows what exists, only changes whats needed
- Plan Before Apply: Preview changes before making them
Installation
==> terraform 1.7.0 installed
Project Structure
infra/terraform/
āāā main.tf # Provider configuration
āāā variables.tf # Input variables
āāā outputs.tf # Output values
āāā vpc.tf # VPC and networking
āāā ecs.tf # ECS cluster and service
āāā alb.tf # Load balancer
āāā rds.tf # Database
āāā s3.tf # S3 buckets
āāā iam.tf # IAM roles and policies
āāā secrets.tf # Secrets Manager
āāā terraform.tfvars # Variable values (git-ignored)Provider Configuration
# main.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Store state in S3 (recommended for teams)
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "my-app/terraform.tfstate"
region = "ap-southeast-1"
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
}Variables
# variables.tf
variable "aws_region" {
description = "AWS region to deploy to"
type = string
default = "ap-southeast-1"
}
variable "project_name" {
description = "Name of the project"
type = string
}
variable "environment" {
description = "Environment (staging, production)"
type = string
validation {
condition = contains(["staging", "production"], var.environment)
error_message = "Environment must be staging or production."
}
}
variable "container_image" {
description = "Docker image URI"
type = string
}
variable "db_password" {
description = "Database password"
type = string
sensitive = true
}Outputs
# outputs.tf
output "alb_dns_name" {
description = "DNS name of the load balancer"
value = aws_lb.main.dns_name
}
output "ecr_repository_url" {
description = "URL of the ECR repository"
value = aws_ecr_repository.app.repository_url
}
output "rds_endpoint" {
description = "RDS instance endpoint"
value = aws_db_instance.main.endpoint
sensitive = true
}Best Practices
- Use remote state with locking
- Never hardcode secrets - use variables with sensitive flag
- Use modules for reusable components
- Run
terraform fmtbefore commits - Review plans carefully before applying
- Use workspaces or separate state files per environment
- Tag all resources for cost tracking
Cost Control with Terraform
Always destroy unused infrastructure to avoid charges:
terraform destroy -var-file=staging.tfvars- Destroy staging environment- Review the plan output carefully - it shows exactly what will be deleted
- Type
yesonly after confirming the resources listed are correct
Warning: Terraform destroy is irreversible. Ensure you have backups of any important data before destroying.
Learning Path