Claude Code के साथ Terraform IaC: AWS module, state और CI की व्यावहारिक गाइड
AWS उदाहरण से Claude Code और Terraform IaC सीखें: module, backend, state, CI, plan review, secrets और common pitfalls.
Terraform से AWS infrastructure बनाना शुरू में आसान लगता है। VPC, subnet और route table लिखे, terraform plan चला, और काम पूरा लगने लगता है। असली समस्या बाद में आती है: state कहाँ रहेगा, dev और prod अलग कैसे रहेंगे, module कितना छोटा होगा, CI किस बदलाव को रोकेगा, और Claude Code से बना code कहीं resource delete तो नहीं कर देगा।
IaC का मतलब Infrastructure as Code है, यानी infrastructure को review होने वाले code की तरह लिखना। HCL Terraform की configuration language है। Module reusable infrastructure हिस्सा है। State वह record है जिससे Terraform जानता है कि cloud में कौन सा resource किस code से जुड़ा है। Backend वह जगह है जहाँ state रखा जाता है। इन शब्दों को साफ समझना जरूरी है, क्योंकि Terraform की ज्यादातर गलतियाँ code, state, permission और human review के बीच होती हैं।
Masa ने इस लेख के लिए छोटे AWS test repo में यह flow चलाया। Claude Code ने VPC module बनाना, variables व्यवस्थित करना और CI draft करना तेज कर दिया। लेकिन prompt में साफ rules डालने पड़े: tfvars में secrets नहीं, destroy वाला plan approve नहीं, और नए S3 backend के लिए पुराना DynamoDB locking pattern नहीं।
Workflow और उपयोग के मामले
सुरक्षित flow यह है: requirement लिखें, Claude Code से HCL draft बनवाएँ, Terraform checks चलाएँ, plan review करें, फिर ही apply करें।
flowchart LR
A["Requirement लिखना"] --> B["Claude Code HCL draft करता है"]
B --> C["terraform fmt / validate"]
C --> D["terraform plan"]
D --> E["AI और human review"]
E --> F["Approved apply"]
काम में ये use cases सबसे उपयोगी हैं।
| Use case | Claude Code क्या कर सकता है | इंसान क्या जरूर देखे |
|---|---|---|
| नया AWS network | VPC, subnets, routes, tags | CIDR conflict, NAT Gateway cost |
| Module design | modules/vpc, variables, outputs | Module बहुत बड़ा तो नहीं |
| Environment split | envs/dev.tfvars, envs/prod.tfvars | Backend key और prod permissions |
| CI और policy | fmt, validate, plan, JSON checks | destroy, replace, IAM expansion |
Claude Code की basic जानकारी के लिएofficial docs देखें। Terraform module concept के लिएTerraform Modules docs उपयोगी हैं। AWS permission समझने के लिए internalAWS IAM guide भी पढ़ें।
Claude Code prompt में safety लिखें
सिर्फ “Terraform code लिखो” न कहें। Scope, forbidden actions और verification commands साथ दें।
claude -p "
AWS VPC module के लिए Terraform बनाइए।
मेरी explicit permission के बिना existing files delete न करें।
Requirements:
- Terraform 1.10 या नया मानें
- hashicorp/aws provider use करें
- VPC, 2 public subnets, 2 private subnets, Internet Gateway, NAT Gateway बनाएँ
- Reusable code modules/vpc में रखें
- dev और prod को tfvars से अलग करें
- secrets या AWS access keys tfvars में न लिखें
- terraform fmt -recursive, terraform validate, terraform plan steps दें
- plan में destroy या replacement हो तो apply approved न मानें
"
यह prompt इसलिए जरूरी है क्योंकि Terraform का generated code real bill, real network और real permissions बदलता है। Claude Code speed देता है, लेकिन production safety की जिम्मेदारी team की रहती है।
AWS Terraform starter structure
यह छोटा structure copy करके start किया जा सकता है। Real plan के लिए AWS credentials और state bucket चाहिए। जून 2026 में Terraform S3 backend use_lockfile से locking support करता है; DynamoDB based locking deprecated बताया गया है। इसलिए पुराने tutorial copy करने से पहलेS3 backend official docs देखें।
infra/
versions.tf
variables.tf
main.tf
envs/dev.tfvars
modules/vpc/main.tf
modules/vpc/variables.tf
modules/vpc/outputs.tf
# versions.tf
terraform {
required_version = ">= 1.10.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0, < 7.0"
}
}
backend "s3" {
bucket = "replace-with-your-tfstate-bucket"
key = "claude-code-terraform-iac/dev/terraform.tfstate"
region = "ap-south-1"
encrypt = true
use_lockfile = true
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = var.common_tags
}
}
# variables.tf
variable "aws_region" {
type = string
description = "AWS region to deploy into."
default = "ap-south-1"
}
variable "environment" {
type = string
description = "Environment name such as dev, staging, or prod."
}
variable "common_tags" {
type = map(string)
description = "Tags applied to every supported AWS resource."
}
variable "vpc_cidr" {
type = string
description = "CIDR block for the VPC."
}
variable "public_subnets" {
type = list(object({
name = string
cidr = string
az = string
}))
}
variable "private_subnets" {
type = list(object({
name = string
cidr = string
az = string
}))
}
# main.tf
module "network" {
source = "./modules/vpc"
project = "claude-code-iac"
environment = var.environment
vpc_cidr = var.vpc_cidr
public_subnets = var.public_subnets
private_subnets = var.private_subnets
common_tags = var.common_tags
}
Module design और variables
VPC module को सिर्फ network तक सीमित रखें। उसी module में ALB, ECS, RDS और IAM जोड़ने से plan बड़ा और review कठिन हो जाता है। Long-lived resources के लिए count.index से बेहतर stable name के साथ for_each है।
# modules/vpc/variables.tf
variable "project" {
type = string
description = "Project name used in resource names."
}
variable "environment" {
type = string
description = "Environment name used in tags and names."
}
variable "vpc_cidr" {
type = string
description = "CIDR block for the VPC."
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "vpc_cidr must be a valid CIDR block."
}
}
variable "public_subnets" {
type = list(object({
name = string
cidr = string
az = string
}))
validation {
condition = length(var.public_subnets) >= 2 && alltrue([for s in var.public_subnets : can(cidrhost(s.cidr, 0))])
error_message = "Define at least two valid public subnet CIDR blocks."
}
}
variable "private_subnets" {
type = list(object({
name = string
cidr = string
az = string
}))
validation {
condition = length(var.private_subnets) >= 2 && alltrue([for s in var.private_subnets : can(cidrhost(s.cidr, 0))])
error_message = "Define at least two valid private subnet CIDR blocks."
}
}
variable "common_tags" {
type = map(string)
description = "Common tags."
}
# modules/vpc/main.tf
locals {
public_subnets_by_name = { for subnet in var.public_subnets : subnet.name => subnet }
private_subnets_by_name = { for subnet in var.private_subnets : subnet.name => subnet }
name_prefix = "${var.project}-${var.environment}"
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(var.common_tags, {
Name = "${local.name_prefix}-vpc"
})
}
resource "aws_subnet" "public" {
for_each = local.public_subnets_by_name
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
map_public_ip_on_launch = true
tags = merge(var.common_tags, {
Name = "${local.name_prefix}-public-${each.key}"
Tier = "public"
})
}
resource "aws_subnet" "private" {
for_each = local.private_subnets_by_name
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
tags = merge(var.common_tags, {
Name = "${local.name_prefix}-private-${each.key}"
Tier = "private"
})
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
for_each = aws_subnet.public
subnet_id = each.value.id
route_table_id = aws_route_table.public.id
}
resource "aws_eip" "nat" {
domain = "vpc"
}
resource "aws_nat_gateway" "main" {
allocation_id = aws_eip.nat.id
subnet_id = values(aws_subnet.public)[0].id
depends_on = [aws_internet_gateway.main]
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main.id
}
}
resource "aws_route_table_association" "private" {
for_each = aws_subnet.private
subnet_id = each.value.id
route_table_id = aws_route_table.private.id
}
State, backend और environment separation
State में resource IDs और कुछ sensitive attributes हो सकते हैं। इसलिए S3 bucket में versioning, locking और strict IAM रखें। dev और prod को अलग backend key दें।
# envs/dev.tfvars
aws_region = "ap-south-1"
environment = "dev"
vpc_cidr = "10.40.0.0/16"
common_tags = {
Project = "claude-code-iac"
Environment = "dev"
Owner = "masa"
ManagedBy = "terraform"
}
public_subnets = [
{ name = "a", cidr = "10.40.0.0/24", az = "ap-south-1a" },
{ name = "b", cidr = "10.40.1.0/24", az = "ap-south-1b" }
]
private_subnets = [
{ name = "a", cidr = "10.40.10.0/24", az = "ap-south-1a" },
{ name = "b", cidr = "10.40.11.0/24", az = "ap-south-1b" }
]
Production में CIDR, tags और backend key अलग होने चाहिए। Workspace भी option है, लेकिन beginners के लिए explicit tfvars files ज्यादा readable रहती हैं।
fmt, validate, plan चलाना
Terraform के official pages fmt, validate, और plan देखें। पहले remote backend के बिना syntax और type check करें।
cd infra
terraform init -backend=false
terraform fmt -recursive
terraform validate
Real AWS changes देखने के लिए backend initialize करें और plan save करें।
terraform init -reconfigure
terraform plan -var-file=envs/dev.tfvars -out=tfplan
terraform show -no-color tfplan > plan.txt
Claude Code को risk-focused review दें।
claude -p "
plan.txt review करें।
destroy, replace, force replacement, IAM permission expansion, public exposure और backend key change को priority दें।
अगर delete action है तो plan approve न करें।
Human reviewer के लिए जरूरी सवाल लिखें।
"
CI, policy, permissions और secrets
GitHub Actions में long-lived AWS access keys न रखें। OIDC से limited IAM role assume करें। Official guide यहाँ है:GitHub Actions OIDC in AWS। IAM role कोAWS IAM best practices के अनुसार छोटा रखें।
name: terraform-plan
on:
pull_request:
paths:
- "infra/**"
permissions:
contents: read
id-token: write
jobs:
plan:
runs-on: ubuntu-latest
defaults:
run:
working-directory: infra
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.10.0"
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-terraform-plan
aws-region: ap-south-1
- run: terraform init -backend=false
- run: terraform fmt -check -recursive
- run: terraform validate
- run: terraform init -reconfigure
- run: terraform plan -var-file=envs/dev.tfvars -out=tfplan
- run: terraform show -json tfplan > tfplan.json
Simple policy delete actions रोक सकती है।
package terraform.deny
deny[msg] {
rc := input.resource_changes[_]
rc.change.actions[_] == "delete"
msg := sprintf("Destroy action requires manual approval: %s", [rc.address])
}
CI flow के लिएClaude Code CI/CD guide और secrets के लिएSecrets management guide देखें।
Common pitfalls और test result
पहली गलती state को temporary file समझना है। उसे Git में commit न करें और dev/prod की key अलग रखें। दूसरी गलती count.index पर ज्यादा भरोसा करना है; list order बदलने से replace आ सकता है। तीसरी गलती passwords, tokens या AWS keys को tfvars में लिखना है। चौथी गलती Claude Code की अच्छी summary देखकर plan apply कर देना है। NAT Gateway, RDS, EKS और IAM changes पर हमेशा human review चाहिए।
इस article के sample को test repo में रखने के बाद terraform fmt -recursive और terraform validate pass हुए। Real plan से पहले backend bucket बदलना और AWS credentials लगाना जरूरी है। Review में सबसे आसानी से छूटने वाली बातें NAT Gateway cost, shared state key और replace actions थीं। Claude Code को destroy और replace पहले देखने को कहना सबसे उपयोगी रहा।
अगर आपकी team Terraform review prompts, CI checklist और IaC onboarding को standard बनाना चाहती है, तोClaude Code resources याimplementation training देखें। Personal project में भी यह prompt और commands CLAUDE.md में रखने से हर Terraform PR ज्यादा safe और repeatable बनता है।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.