What is Terraform?
Terraform is an open-source Infrastructure as Code (IaC) tool created by HashiCorp. It lets you define and provision infrastructure using a declarative configuration language called HCL (HashiCorp Configuration Language). Terraform supports hundreds of cloud providers and services, enabling you to manage your entire infrastructure lifecycle — create, update, and destroy — through code.
Why Terraform?
- Multi-Cloud: Works with AWS, GCP, Azure, Kubernetes, and 3000+ providers
- Declarative: Define what you want, not how to get there
- State Management: Tracks the real-world state of your infrastructure
- Plan Before Apply: Preview changes before making them
- Modular: Reuse infrastructure code with modules
- Version Controlled: Infrastructure changes are tracked in Git like application code
Installing Terraform
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# Linux
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
# Enable autocompletion
terraform -install-autocomplete
Terraform Core Workflow
Terraform follows a simple workflow: Write configuration, Plan changes, and Apply the plan. This three-step process ensures you always know what will change before it happens.
# Initialize the working directory (download providers)
terraform init
# Format configuration files
terraform fmt
# Validate configuration syntax
terraform validate
# Preview changes (dry run)
terraform plan
# Apply changes
terraform apply
# Apply with auto-approve (CI/CD pipelines)
terraform apply -auto-approve
# Destroy all resources
terraform destroy
# Show current state
terraform show
# List resources in state
terraform state list
Your First Terraform Configuration
# main.tf - AWS S3 bucket + CloudFront distribution
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Remote state storage (recommended for teams)
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "production/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "terraform"
Project = var.project_name
}
}
}
# S3 bucket for static website
resource "aws_s3_bucket" "website" {
bucket = "${var.project_name}-${var.environment}-website"
}
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document {
suffix = "index.html"
}
error_document {
key = "404.html"
}
}
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_policy" "website" {
bucket = aws_s3_bucket.website.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "PublicReadGetObject"
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.website.arn}/*"
}]
})
}
Variables and Outputs
# variables.tf
variable "aws_region" {
description = "AWS region to deploy resources"
type = string
default = "us-east-1"
}
variable "environment" {
description = "Environment name (development, staging, production)"
type = string
validation {
condition = contains(["development", "staging", "production"], var.environment)
error_message = "Environment must be development, staging, or production."
}
}
variable "project_name" {
description = "Project name used for resource naming"
type = string
}
variable "instance_count" {
description = "Number of EC2 instances"
type = number
default = 2
}
variable "allowed_cidrs" {
description = "List of CIDR blocks allowed to access the application"
type = list(string)
default = ["0.0.0.0/0"]
}
variable "tags" {
description = "Additional tags for resources"
type = map(string)
default = {}
}
# outputs.tf
output "website_url" {
description = "URL of the S3 static website"
value = aws_s3_bucket_website_configuration.website.website_endpoint
}
output "bucket_arn" {
description = "ARN of the S3 bucket"
value = aws_s3_bucket.website.arn
}
output "bucket_name" {
description = "Name of the S3 bucket"
value = aws_s3_bucket.website.id
}
# terraform.tfvars (environment-specific values)
aws_region = "us-east-1"
environment = "production"
project_name = "my-web-app"
# Apply with var file
terraform plan -var-file="production.tfvars"
terraform apply -var-file="production.tfvars"
Key Takeaways
- Terraform is the leading multi-cloud IaC tool — write once, deploy anywhere
- The workflow is: init, plan, apply — always review the plan before applying
- Use variables for reusable configs, outputs to expose values to other modules
- Store state remotely (S3, GCS, Azure Blob) with locking for team collaboration
- Version control all Terraform code and use code review for infrastructure changes