Skilllibrary terraform-iac
Write and manage Terraform infrastructure — author HCL modules, configure providers and backends, manage state files, run plan/apply workflows, detect drift, and structure multi-environment deployments. Use when creating or editing .tf files, debugging Terraform plan output, refactoring modules, or configuring remote state. Do not use for Pulumi, CloudFormation, or other IaC tools outside the Terraform ecosystem.
install
source · Clone the upstream repo
git clone https://github.com/merceralex397-collab/skilllibrary
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/14-cloud-platform-devops/terraform-iac" ~/.claude/skills/merceralex397-collab-skilllibrary-terraform-iac && rm -rf "$T"
manifest:
14-cloud-platform-devops/terraform-iac/SKILL.mdsource content
Purpose
Write and manage Terraform infrastructure-as-code — author HCL resource definitions and reusable modules, configure providers and remote state backends, run
plan/apply workflows safely, detect and resolve state drift, and structure multi-environment deployments with workspaces or directory-based separation.
When to use this skill
- Creating new
files to define cloud infrastructure (VPCs, instances, databases, IAM, etc.).tf - Editing existing Terraform modules or resource definitions
- Configuring a remote state backend (S3 + DynamoDB, GCS, Terraform Cloud)
- Debugging
output — understanding what will be created, changed, or destroyedterraform plan - Refactoring inline resources into reusable modules
- Setting up multi-environment structure (dev/staging/prod) with shared modules
- Resolving state drift, importing existing resources, or recovering from state corruption
- Configuring provider authentication and version constraints
Do not use this skill when
- The IaC tool is Pulumi, CloudFormation, CDK, or Ansible — this skill is Terraform-only
- The task is application code changes with no infrastructure component
- The task is platform-specific deployment config (Vercel, Heroku) without Terraform involvement
- The task is Docker image building — use
(Terraform can deploy containers but does not build images)docker-containers
Operating procedure
- Assess the current Terraform state. Run
to initialize providers and backend. Runterraform init
to see the current delta between code and infrastructure. Check for any existing drift. Reviewterraform plan
for provider version pins..terraform.lock.hcl - Structure the project layout. Organize files by concern:
— primary resource definitionsmain.tf
— input variable declarations with types, descriptions, and defaultsvariables.tf
— output value definitionsoutputs.tf
— provider configuration and version constraintsproviders.tf
— remote state backend configurationbackend.tf
—versions.tf
andrequired_version
blockrequired_providers
— reusable modules, each with their ownmodules/
,main.tf
,variables.tfoutputs.tf
- Configure the remote state backend. Set up S3 + DynamoDB (AWS), GCS (GCP), or Terraform Cloud as the backend. Enable state locking. Configure the backend block in
with bucket, key, region, DynamoDB table (for S3), andbackend.tf
. Runencrypt = true
if switching backends.terraform init -migrate-state - Write resource definitions. Define resources using the provider's resource types. Use
sources to reference existing infrastructure. Always set explicitdata
only when Terraform cannot infer the dependency automatically. Tag all resources with at minimumdepends_on
,Name
, andEnvironment
.ManagedBy = "terraform" - Extract reusable modules. When a resource pattern repeats across environments, extract it into a module under
. Define all configurable values as input variables. Output IDs and ARNs that downstream resources need. Pin the module source version when referencing remote modules.modules/{module-name}/ - Structure multi-environment deployments. Choose one approach:
- Directory-based: separate directories per environment (
,envs/dev/
) each with their ownenvs/prod/
andbackend.tf
, calling shared modulesterraform.tfvars - Workspace-based: single directory using
— simpler but riskier for production (easy to apply to the wrong workspace)terraform workspace - Prefer directory-based for production systems.
- Directory-based: separate directories per environment (
- Run the plan/apply workflow. Always run
first. Review the plan output line by line — check for unexpected destroys or replacements. Only proceed withterraform plan -out=tfplan
after confirming the plan is correct. In CI/CD, store the plan artifact and require human approval before apply.terraform apply tfplan - Handle state operations carefully. For importing existing resources:
. For removing resources from state without destroying:terraform import {resource_type}.{name} {cloud_id}
. For moving resources between modules:terraform state rm {resource_address}
. Always back up state before state operations:terraform state mv {old_address} {new_address}
.terraform state pull > state-backup.json - Detect and resolve drift. Run
regularly (in CI on a schedule). If drift is detected, determine whether the infrastructure change was intentional (update the code to match) or accidental (runterraform plan
to reconcile). Document the drift resolution in the commit message.terraform apply - Validate and format. Run
to enforce canonical formatting. Runterraform fmt -recursive
to catch syntax and type errors. Useterraform validate
for provider-specific lint rules. Run these in CI as a gate before plan.tflint - Lock provider versions. Pin provider versions in
usingversions.tf
(pessimistic constraint) to allow patch updates but not minor/major. Commit~>
to version control. Update providers deliberately with.terraform.lock.hcl
.terraform init -upgrade
Decision rules
- If
shows a resource will be destroyed and recreated, investigate theterraform plan
reason before proceeding — this often indicates a non-updatable attribute change.forces replacement - If state is corrupted or lost, do not run
— first restore from backup or reimport all resources.terraform apply - If a module is used by more than two environments, it must live in
with versioned releases — not copy-pasted inline.modules/ - If the plan shows more than 20 changes, split the work into smaller targeted applies using
— then remove the target flag in follow-up runs.-target - Prefer
for simple conditional resources andcount
for collections. Never usefor_each
to iterate over a list of distinct resources — usecount
with a map.for_each - If a resource attribute is sensitive (passwords, keys), mark it with
in the variable and output definitions.sensitive = true
Output requirements
- HCL files — complete
files with resources, variables, outputs, and provider config.tf - Plan output —
output showing the expected changesterraform plan - Module structure — module directory layout with
,variables.tf
,main.tfoutputs.tf - Backend configuration — remote state backend config with locking enabled
- CI/CD integration — plan/apply pipeline steps (if modifying CI/CD)
References
- Terraform documentation: https://developer.hashicorp.com/terraform/docs
- Terraform language reference: https://developer.hashicorp.com/terraform/language
- Terraform best practices: https://developer.hashicorp.com/terraform/cloud-docs/recommended-practices
- tflint: https://github.com/terraform-linters/tflint
- Terraform state management: https://developer.hashicorp.com/terraform/language/state
Related skills
— for AWS provider resources and IAM configurationaws
— for GCP provider resources and IAM bindingsgcp
— for Terraform-managed container infrastructuredocker-containers
— for managing secrets referenced in Terraform configssecret-management
Anti-patterns
- Running
without reviewing the plan output firstterraform apply - Using
in production without a prior saved planterraform apply -auto-approve - Storing state files locally or in version control instead of a remote backend with locking
- Hardcoding environment-specific values instead of using variables and
files.tfvars - Using
to force recreation whenterraform taint
is available (v0.15.2+)terraform apply -replace - Creating monolithic
files with hundreds of resources instead of splitting into modulesmain.tf - Using
as a permanent workflow instead of fixing the dependency graph-target
Failure handling
- If
fails with provider errors, runterraform plan
to refresh providers. Check that credentials are configured (terraform init -upgrade
,AWS_PROFILE
, etc.).GOOGLE_APPLICATION_CREDENTIALS - If
fails mid-way, do not panic — Terraform records partial state. Runterraform apply
to see the remaining delta and re-apply.terraform plan - If state locking fails (
), check for stale locks. UseError acquiring the state lock
only after confirming no other apply is running.terraform force-unlock {lock-id} - If a resource is manually deleted outside Terraform, run
to detect the drift, then either reimport or let Terraform recreate it.terraform plan - If a module upgrade introduces breaking changes, pin the previous version, review the changelog, and update variable usage before upgrading.