Terrafom tutorial from beginner to advance with production grade projects






AI-Generated Content
— This tutorial was generated with AI assistance. Always validate commands and code in a safe environment before running in production. Review AWS pricing and IAM permissions carefully.
Beginner · Modules 1–4
MODULE 01
Setup & Core Concepts
Install Terraform, configure AWS credentials, and understand the fundamental workflow.
terraform installHCL syntaxprovidersresourcesinit/plan/apply/destroy

What is Terraform?

An Infrastructure as Code (IaC) tool. Describe infrastructure in .tf files using HCL, and Terraform creates/manages it on AWS or any cloud.

  • terraform initDownload providers, set up backend
  • terraform planPreview changes (dry run)
  • terraform applyCreate/update infrastructure
  • terraform destroyTear down all resources
  • terraform fmtAuto-format .tf files
  • terraform validateCheck config for errors
main.tfHCL
# Configure the AWS provider
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

# Create an EC2 instance
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags = { Name = "MyFirstServer" }
}
Warning

Always run terraform plan before apply. Look for unexpected destroys (shown in red with -).

MODULE 02
Variables & Outputs
Make configs reusable with input variables, output values, locals, and data sources.
variableoutputlocalsdata sources.tfvars
variables.tfHCL
variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

resource "aws_instance" "web" {
  instance_type = var.instance_type
}

locals {
  env  = "dev"
  name = "myapp-${local.env}"
}

output "instance_ip" {
  value = aws_instance.web.public_ip
}
data.tfHCL
# Fetch latest Amazon Linux 2 AMI
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

resource "aws_instance" "web" {
  ami = data.aws_ami.amazon_linux.id
}
Tip

Put values in terraform.tfvars. Never commit secrets — use TF_VAR_name env vars or AWS Secrets Manager.

MODULE 03
State Management
Terraform tracks what it created in a state file. Understanding state is critical to avoiding disasters.
terraform.tfstatestate commandsimportstate locking

What is state?

terraform.tfstate maps your config to real AWS resources. It records IDs, metadata, and dependencies.

  • terraform state listList all resources in state
  • terraform state show aws_instance.webShow resource attributes
  • terraform state rm aws_instance.webRemove from state (keeps AWS resource)
  • terraform import aws_instance.web i-1234Import existing resource into state
imports.tfHCL (Terraform 1.5+)
import {
  to = aws_instance.existing
  id = "i-0a1b2c3d4e5f67890"
}
Warning

Never manually edit terraform.tfstate. For teams, use remote state (Module 7).

MODULE 04
Core AWS Resources
Essential building blocks: EC2, S3, IAM, and security groups.
aws_instanceaws_s3_bucketaws_iam_roleaws_security_group
main.tfHCL
# Security group
resource "aws_security_group" "web_sg" {
  name = "web-sg"
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# EC2 with security group
resource "aws_instance" "web" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web_sg.id]
  user_data = <<-EOF
    #!/bin/bash
    yum install -y httpd
    systemctl start httpd
  EOF
}
Tip

Always prefer IAM roles over access keys for EC2. Instances get temporary credentials automatically — no secrets to manage.

★ Beginner Project

Static Website on S3 + CloudFront

Deploy a static website using S3 for storage and CloudFront as the CDN.

1Create S3 bucket with static website hosting
2Upload index.html via aws_s3_object
3Create CloudFront distribution
4Create IAM OAC for S3 access
5Output the CloudFront URL
6Apply, test the URL, then destroy
Intermediate · Modules 5–9
MODULE 05
Modules
Package reusable infrastructure into modules and share across projects.
module blocksinputs/outputsregistryversioning

What is a module?

A directory of .tf files. Call with a module block, pass variables, get outputs. Root = your main dir; child = subdirs or registry.

main.tfHCL
# Use a registry module
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"
  name    = "my-vpc"
  cidr    = "10.0.0.0/16"
}

# Access module outputs
resource "aws_instance" "web" {
  subnet_id = module.vpc.public_subnets[0]
}
MODULE 06
Networking — VPC Deep Dive
Production networking: VPC, subnets, route tables, NAT gateways.
aws_vpcsubnetsroute tablesNAT gateway
vpc.tfHCL
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.0"
  name    = "prod-vpc"
  cidr    = "10.0.0.0/16"

  azs             = ["us-east-1a", "us-east-1b"]
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.11.0/24", "10.0.12.0/24"]

  enable_nat_gateway = true
  single_nat_gateway = true
}
Cost Warning

NAT Gateways cost ~$0.045/hr. Use single_nat_gateway = true for learning. Always terraform destroy when done.

MODULE 07
Remote State & Workspaces
Store state in S3 with DynamoDB locking for team collaboration.
S3 backendDynamoDB lockingworkspaces
backend.tfHCL
terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
  • terraform workspace new stagingCreate a new workspace
  • terraform workspace select prodSwitch to prod
  • terraform workspace listList all workspaces
MODULE 08
Compute & Load Balancing
Auto Scaling Groups, Application Load Balancers, and RDS databases.
ASGALBRDSlaunch templates
asg.tfHCL
resource "aws_launch_template" "web" {
  name_prefix   = "web-"
  image_id      = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"
}

resource "aws_autoscaling_group" "web" {
  desired_capacity    = 2
  max_size            = 5
  min_size            = 1
  target_group_arns   = [aws_lb_target_group.web.arn]
  vpc_zone_identifier = module.vpc.private_subnets

  launch_template {
    id      = aws_launch_template.web.id
    version = "$Latest"
  }
}
MODULE 09
CI/CD Integration
Automate Terraform with GitHub Actions using OIDC — no stored credentials.
GitHub ActionsOIDCplan on PRapply on merge
.github/workflows/terraform.ymlYAML
name: Terraform
on:
  push: { branches: [main] }
  pull_request:
permissions:
  id-token: write
  contents: read
jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GHRole
          aws-region: us-east-1
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform plan
        if: github.event_name == 'pull_request'
      - run: terraform apply -auto-approve
        if: github.ref == 'refs/heads/main'
OIDC

GitHub Actions assumes an AWS IAM role directly via OpenID Connect. No long-lived access keys stored in GitHub secrets.

★ Intermediate Project

3-Tier Web App on AWS

Production architecture: VPC + ALB + ASG + RDS with CI/CD.

1Create S3 + DynamoDB backend for remote state
2Build VPC with public + private subnets
3Create ALB in public subnets + target group
4Launch template + ASG in private subnets
5Add RDS PostgreSQL in private subnets
6Store DB password in AWS Secrets Manager
7GitHub Actions OIDC CI/CD pipeline
Advanced · Modules 10–15
MODULE 10
Advanced HCL
for_each, dynamic blocks, complex types, and lifecycle rules.
for_eachcountdynamic blockslifecycle
advanced.tfHCL
# for_each over a map
resource "aws_s3_bucket" "all" {
  for_each = { "logs" = "us-east-1", "backups" = "us-west-2" }
  bucket   = "myapp-${each.key}"
}

# Dynamic block — avoid repeating ingress rules
resource "aws_security_group" "web" {
  dynamic "ingress" {
    for_each = [80, 443, 8080]
    content {
      from_port   = ingress.value
      to_port     = ingress.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

# Lifecycle rules
resource "aws_instance" "web" {
  lifecycle {
    create_before_destroy = true
    prevent_destroy       = true
    ignore_changes        = [ami]
  }
}
MODULE 11
Containers — ECS & EKS
Deploy containers on ECS Fargate or EKS with Helm.
ECSFargateECREKSHelm
ecs.tfHCL
resource "aws_ecs_cluster" "main" {
  name = "app-cluster"
}

resource "aws_ecs_task_definition" "app" {
  family                   = "app"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu    = "256"
  memory = "512"
  container_definitions = jsonencode([{
    name  = "app"
    image = "nginx:latest"
    portMappings = [{ containerPort = 80 }]
  }])
}

resource "aws_ecs_service" "app" {
  name            = "app"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 2
  launch_type     = "FARGATE"
}
MODULE 12
Serverless & Event-Driven
Lambda, API Gateway, SQS, and DynamoDB in Terraform.
LambdaAPI GatewaySQSDynamoDB
lambda.tfHCL
data "archive_file" "zip" {
  type        = "zip"
  source_file = "lambda/handler.py"
  output_path = "lambda/handler.zip"
}

resource "aws_lambda_function" "api" {
  filename         = data.archive_file.zip.output_path
  function_name    = "my-api"
  role             = aws_iam_role.lambda_role.arn
  handler          = "handler.lambda_handler"
  runtime          = "python3.12"
  source_code_hash = data.archive_file.zip.output_base64sha256
}

resource "aws_apigatewayv2_api" "api" {
  name          = "my-api"
  protocol_type = "HTTP"
  target        = aws_lambda_function.api.arn
}
MODULE 13
Terragrunt
Keep Terraform DRY across environments with dependency management.
terragrunt.hclDRY configsdependenciesrun-all
live/prod/vpc/terragrunt.hclHCL
include "root" {
  path = find_in_parent_folders()
}

terraform {
  source = "../../../modules/vpc"
}

inputs = {
  cidr        = "10.1.0.0/16"
  environment = "prod"
}
MODULE 14
Security & Compliance
Scan configs with tfsec/Checkov. Enforce policies with OPA. Detect drift.
tfsecCheckovTrivyOPAdrift detection
terminalbash
tfsec .                              # Fast static analysis
checkov -d .                         # Broad policy checks
trivy config .                       # Vulnerability scan
terraform plan -detailed-exitcode    # Exit 2 = drift detected
CI/CD

Add tfsec or Checkov before terraform plan in GitHub Actions. Fail pipeline on HIGH/CRITICAL findings.

MODULE 15
Multi-Region & Multi-Account
Provider aliases, AWS Organizations, and cross-account IAM roles.
provider aliasesOrganizationscross-account roles
multi_region.tfHCL
provider "aws" {
  alias  = "primary"
  region = "us-east-1"
}
provider "aws" {
  alias  = "dr"
  region = "us-west-2"
}

resource "aws_s3_bucket" "primary" {
  provider = aws.primary
  bucket   = "myapp-primary"
}
resource "aws_s3_bucket" "dr" {
  provider = aws.dr
  bucket   = "myapp-dr-replica"
}

# Cross-account assume role
provider "aws" {
  alias = "prod_account"
  assume_role {
    role_arn = "arn:aws:iam::PROD_ID:role/TerraformRole"
  }
}
★ Advanced Capstone Project

Production EKS Platform (Multi-Account)

Build a full production platform using everything in this course.

1AWS Organizations with dev/staging/prod accounts
2Terragrunt with per-account state backends
3Shared VPC per environment
4EKS cluster with managed node groups
5ALB Ingress Controller + Cluster Autoscaler via Helm
6RDS Aurora with Secrets Manager rotation
7Lambda + SQS event processing pipeline
8GitHub Actions OIDC CI/CD pipeline
9OPA policies: required tags + no public S3
10CloudTrail + Config rules for audit & drift