DocsTerraform IaC

🏗️ Terraform Infrastructure as Code

Learn how to manage cloud infrastructure using Terraform, the industry-leading IaC tool.

What is Terraform?

Terraform is an open-source infrastructure as code tool that lets you define and provision infrastructure using a declarative configuration language (HCL).

Installation

# macOS
brew install terraform
 
# Ubuntu/Debian
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
 
# Verify installation
terraform version

Basic Workflow

# Initialize working directory
terraform init
 
# Preview changes
terraform plan
 
# Apply changes
terraform apply
 
# Destroy resources
terraform destroy

AWS EC2 Example

Create a simple EC2 instance:

# main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
 
provider "aws" {
  region = var.aws_region
}
 
# Variables
variable "aws_region" {
  description = "AWS region"
  default     = "ap-southeast-1"
}
 
variable "instance_type" {
  description = "EC2 instance type"
  default     = "t3.micro"
}
 
# Data source for latest Ubuntu AMI
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical
 
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}
 
# EC2 Instance
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
 
  tags = {
    Name        = "WebServer"
    Environment = "Development"
    ManagedBy   = "Terraform"
  }
}
 
# Output
output "instance_public_ip" {
  description = "Public IP of the EC2 instance"
  value       = aws_instance.web.public_ip
}

VPC with Subnets

# vpc.tf
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
 
  tags = {
    Name = "main-vpc"
  }
}
 
resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
 
  map_public_ip_on_launch = true
 
  tags = {
    Name = "public-subnet-${count.index + 1}"
    Type = "Public"
  }
}
 
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
 
  tags = {
    Name = "main-igw"
  }
}
 
data "aws_availability_zones" "available" {
  state = "available"
}

State Management

Remote Backend (S3)

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "ap-southeast-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Essential Commands

CommandDescription
terraform initInitialize directory
terraform planPreview changes
terraform applyApply changes
terraform destroyDestroy resources
terraform fmtFormat code
terraform validateValidate config
terraform outputShow outputs
terraform state listList state resources

Best Practices

  1. Use modules to organize and reuse code
  2. Store state remotely with locking
  3. Use variables for flexibility
  4. Tag all resources for cost tracking
  5. Use workspaces for environments
  6. Implement CI/CD for IaC

⚠️ Warning: Never commit .tfstate files or .tfvars with secrets to version control!


Related: AWS CloudFormation