Skip to main content

Infrastructure as Code with Terraform: From Zero to Production

Learn Infrastructure as Code with Terraform — from your first resource to production-ready modules, state management, and CI integration.

N
Neeraj Jha
·Updated September 4, 2026·10 min read·124 views
Infrastructure as Code with Terraform: From Zero to Production

Infrastructure as Code with Terraform: From Zero to Production

Terraform by HashiCorp lets you define cloud infrastructure in declarative configuration files. You describe your desired state and Terraform figures out how to get there.

Why Infrastructure as Code?

  • Reproducibility — spin up identical environments in minutes
  • Version control — review infra changes in pull requests
  • Automation — no more clicking through cloud consoles
  • Documentation — your code is your documentation

Installing Terraform

bash
# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Verify
terraform version

Your First Configuration

Create a main.tf file:

hcl
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

variable "aws_region" {
  default = "us-east-1"
}

resource "aws_s3_bucket" "app_assets" {
  bucket = "my-app-assets-${random_id.suffix.hex}"

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

resource "random_id" "suffix" {
  byte_length = 4
}

output "bucket_name" {
  value = aws_s3_bucket.app_assets.bucket
}

Core Workflow

bash
# Initialize — downloads provider plugins
terraform init

# Plan — preview what will change
terraform plan

# Apply — create/update resources
terraform apply

# Destroy — tear everything down
terraform destroy

State Management

Terraform tracks resources in a state file. For teams, store state remotely:

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

Modules

Organize reusable infrastructure into modules:

modules/
  vpc/
    main.tf
    variables.tf
    outputs.tf
  ecs/
    main.tf
    variables.tf
    outputs.tf

Reference them:

hcl
module "vpc" {
  source = "./modules/vpc"
  cidr   = "10.0.0.0/16"
}

module "ecs" {
  source    = "./modules/ecs"
  vpc_id    = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
}

Best Practices

  • Never commit state files — add *.tfstate* to .gitignore
  • Use workspaces or separate state files per environment
  • Pin provider versions to avoid breaking changes
  • Run terraform plan in CI on every pull request
  • Use terraform fmt and terraform validate as pre-commit hooks
  • Tag every resource with ManagedBy = "terraform"

Common Gotchas

  1. Deleting resources from config doesn't destroy them until you run apply
  2. Renaming a resource destroys the old one and creates a new one — use moved blocks
  3. Always use -auto-approve only in automated pipelines, never interactively

Terraform pairs beautifully with CI/CD pipelines. Add a plan step on PRs and an apply step on merge to main for fully automated infrastructure.

Enjoyed this article?

Get more DevOps insights delivered to your inbox.

Get new posts by email

Subscribe to get an email when a new blog post is published. Skip anytime.

No spam, unsubscribe anytime.

N

Written by

Neeraj Jha

Platform administrator and lead writer.

View all posts

Discussion

0 comments

Sign in to join the conversation.

Be the first to comment

Start a conversation about this post

Share: