TechLead
Lesson 19 of 25
5 min read
Cloud & Kubernetes

Terraform Basics

Learn HashiCorp Terraform fundamentals — providers, resources, variables, outputs, state management, and your first infrastructure deployment

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

Continue Learning