Find the Best Cosmetic Hospitals

Explore trusted cosmetic hospitals and make a confident choice for your transformation.

โ€œInvest in yourself โ€” your confidence is always worth it.โ€

Explore Cosmetic Hospitals

Start your journey today โ€” compare options in one place.

Terraform Developer Productivity Master Guide

Tools, Workflow, Security, Testing, CI/CD, Automation, AI Assistance, Governance, and Production Best Practices

Verified baseline: 5 September 2026
Audience: Terraform developers, DevOps/SRE, platform/cloud engineers, module authors, DevSecOps teams, and engineering leaders.

This handbook treats Terraform development as an engineering system, not a collection of unrelated commands. The goal is a fast local feedback loop, reproducible plans, secure authentication, reviewable changes, automated quality gates, policy enforcement, controlled production execution, and continuous drift/health feedback.


Executive standard

A strong default stack for a professional Terraform team is:

VS Code / Cursor / Claude Code
        โ†“
HashiCorp Terraform Extension + terraform-ls
        โ†“
Terraform MCP Server for current Registry/HCP context
        โ†“
tenv
        โ†“
Terraform CLI
        โ†“
terraform fmt
terraform validate
terraform test
        โ†“
TFLint
        โ†“
Trivy
        โ†“
terraform-docs
        โ†“
Infracost
        โ†“
pre-commit-terraform
        โ†“
Git
        โ†“
GitHub / GitLab
        โ†“
CI quality gates + OIDC/workload identity
        โ†“
HCP Terraform / Terraform Enterprise or another controlled runner
        โ†“
Sentinel / OPA / Terraform Policy where appropriate
        โ†“
Cloud infrastructure
        โ†“
Post-deployment validation + drift/health monitoring

Tool classification

Tool / capabilityDefault classificationWhy
Terraform CLIMUST HAVECore IaC engine
GitMUST HAVEReviewable, auditable change history
terraform fmtMUST HAVECanonical formatting
terraform validateMUST HAVEConfiguration validity
Remote state + lockingMUST HAVE for teamsPrevents local-state drift and concurrent writes
Provider/module version constraintsMUST HAVEReproducibility
.terraform.lock.hcl in GitMUST HAVE for root configurationsReproducible provider selection/checksums
VS Code + HashiCorp extensionSTRONGLY RECOMMENDEDFast authoring feedback
terraform-lsSTRONGLY RECOMMENDEDIDE intelligence; usually bundled
tenvSTRONGLY RECOMMENDEDReproducible CLI versions
TFLintSTRONGLY RECOMMENDEDTerraform/provider-aware linting
TrivySTRONGLY RECOMMENDEDIaC misconfiguration + optional secret scanning
terraform testSTRONGLY RECOMMENDEDNative module/root tests
terraform-docsSTRONGLY RECOMMENDED for modulesPrevents stale README interfaces
pre-commit-terraformSTRONGLY RECOMMENDEDCheap local automation
CI plan workflowMUST HAVE for production teamsReproducible review gate
OIDC/workload identityMUST HAVE for CI cloud authAvoids static cloud credentials
InfracostRECOMMENDEDPR-level cost feedback
RenovateRECOMMENDEDDependency hygiene
Terraform MCP ServerRECOMMENDED with AI codingCurrent Registry/HCP context
CheckovOPTIONAL / context dependentStrong policy/compliance scanning; can overlap Trivy
TerratestOPTIONALReal integration/E2E testing when native tests are insufficient
TerragruntOPTIONALUseful for large repeated multi-account/region layouts
AtlantisOPTIONALPR-driven execution if it fits the operating model
HCP TerraformRECOMMENDED / ENTERPRISERemote runs, state, governance, registry, RBAC
Terraform EnterpriseENTERPRISESelf-hosted HCP Terraform distribution
Sentinel / OPAENTERPRISE / governancePolicy gates
ConftestOPTIONALLightweight vendor-neutral Rego execution
tfupdateOPTIONAL / nicheFocused Terraform version rewriting; Renovate is broader

2026-specific guidance

  1. Terraform MCP Server is now a first-class optionย for AI-assisted Terraform. Use it to ground an AI agent in current provider/module documentation instead of trusting model memory.
  2. Nativeย terraform testย is the default first testing layer.ย Add Terratest when you truly need live system behavior, cross-service checks, retries, or non-Terraform assertions.
  3. Trivy is the normal replacement for tfsecย in new workflows.
  4. For new S3 backends use native S3 state lockingย (use_lockfile = true). Do not design a new backend around DynamoDB locking.
  5. HCP Terraform policy choices are broader than Sentinel alone.ย OPA is supported and HashiCorp also has Terraform Policy in HCL; treat beta features cautiously.
  6. Terragrunt 1.x uses the streamlined CLI, e.g.ย terragrunt run --all plan; oldย run-allย examples should be considered legacy.
  7. Do not build CI around static AWS/Azure/GCP keys.ย Use GitHub/GitLab OIDC or the cloud’s workload-identity mechanism.

PART 1 โ€” Terraform Development Ecosystem

1.1 The end-to-end model

Developer intent
   โ†“
Editor / AI coding environment
   โ†“
Language intelligence
   โ†“
Version-controlled Terraform CLI
   โ†“
Fast local quality gates
   โ†“
Git change
   โ†“
CI reproducibility gates
   โ†“
Plan
   โ†“
Security / cost / policy review
   โ†“
Human approval
   โ†“
Controlled apply
   โ†“
Verification
   โ†“
Drift / health feedback

Responsibility of each layer

LayerResponsibilityTypical tools
EditorWrite/navigate/refactor HCLVS Code, Cursor
AI assistantBoilerplate, explanation, refactoringClaude Code, Cursor, VS Code AI
Language serverSchema-aware completion/diagnostics/navigationterraform-ls
AI context serverCurrent Terraform Registry/HCP informationTerraform MCP Server
Version managerSelect project-approved binariestenv, mise, asdf, tfenv
Terraform engineInit/plan/apply/state/testTerraform CLI
FormatterCanonical HCL styleterraform fmt
ValidatorTerraform language/module validityterraform validate
LinterTerraform/provider best practicesTFLint
Security scannerMisconfiguration/compliance/secret checksTrivy, Checkov
Test layerBehavior assertionsterraform test, Terratest
DocumentationGenerate module interface docsterraform-docs
Cost analysisEstimate cost deltaInfracost
Commit automationRun cheap checks before pushpre-commit / pre-commit-terraform
VCSReview/auditGitHub, GitLab
CIReproduce quality gates and create planGitHub Actions, GitLab CI
Remote runner/orchestratorControlled execution/state/governanceHCP Terraform, TFE, Atlantis
Policy as codeOrganizational guardrailsTerraform Policy, Sentinel, OPA
CloudActual infrastructureAWS, Azure, GCP, SaaS providers

Core principle: different tools answer different questions

fmt       โ†’ Is the code formatted?
validate  โ†’ Is the Terraform configuration structurally valid?
TFLint    โ†’ Is it suspicious, deprecated, inconsistent, or provider-invalid?
Trivy     โ†’ Is it insecure or dangerously configured?
test      โ†’ Does the module satisfy its intended behavior?
plan      โ†’ What will Terraform change in this real context?
Infracost โ†’ What may the cost impact be?
Policy    โ†’ Is the change allowed by organizational rules?
Review    โ†’ Should we make this change?
Apply     โ†’ Execute the approved change.
Verify    โ†’ Did the system reach the expected state?
Code language: JavaScript (javascript)

No single tool replaces the others.


PART 2 โ€” Core Terraform Development Tools

2. Terraform CLI

What

Terraform CLI is the execution engine for Terraform configuration, dependency initialization, planning, applying, state operations, testing, and inspection.

Essential command map

CommandUse it whenProduction note
terraform initFirst run, provider/module/backend changesReview lock-file changes
terraform fmtDuring authoring and before commitAutomate
terraform validateAfter editing modules/configDoes not validate live cloud behavior
terraform planBefore any changeReview replacements/destruction
terraform applyExecute an approved planPrefer controlled runner
terraform destroyIntentionally remove stackHigh-risk; require strong controls
terraform consoleTest expressions/functionsGreat for debugging locals/CIDR logic
terraform outputRead root outputsAvoid exposing sensitive values
terraform showInspect state or saved planPlan/state can contain secrets
terraform providersInspect provider dependenciesUseful for upgrade debugging
terraform stateControlled state inspection/movesHigh-risk; use change procedure
terraform importBring existing resources under managementPrefer reviewable import workflows
terraform testExecute .tftest.hcl testsDefault first test framework

Practical workflow

terraform version
terraform init
terraform fmt -recursive
terraform validate
terraform test
terraform plan -out=tfplan
terraform show tfplan
<em># apply only after review/approval</em>
terraform apply tfplan
Code language: HTML, XML (xml)

terraform init

What it does:

  • Initializes backend.
  • Downloads providers.
  • Downloads child modules.
  • Creates/updatesย .terraform.lock.hcl.
  • Prepares the working directory.

Useful patterns:

terraform init
terraform init -upgrade
terraform init -backend=false   <em># useful for validation jobs that do not need state</em>
terraform init -reconfigure
Code language: HTML, XML (xml)

Use -upgrade deliberately, not on every CI run, because it tells Terraform to re-evaluate dependency selections.

terraform fmt

terraform fmt
terraform fmt -recursive
terraform fmt -check -recursive

Local development: run write mode.
CI: run -check so CI detects unformatted code without modifying the branch.

terraform validate

terraform init -backend=false
terraform validate
Code language: JavaScript (javascript)

Validates Terraform configuration consistency and syntax in an initialized directory. It does not prove:

  • credentials are valid,
  • resource values are allowed by the cloud API,
  • IAM permissions are sufficient,
  • deployment will succeed,
  • architecture is secure,
  • cost is acceptable.

Those require lint/security/plan/test/policy/runtime checks.

terraform plan

terraform plan
terraform plan -out=tfplan
terraform show -no-color tfplan
terraform show -json tfplan > tfplan.json

Review especially:

  • -/+ย replacements,
  • deletions,
  • IAM changes,
  • network exposure,
  • encryption changes,
  • database/storage replacement,
  • identity-provider changes,
  • state moves/imports,
  • count/for_each key churn.

Do not treat “Plan: 1 to add, 0 to change, 0 to destroy” as sufficient review. The kind of resource matters.

terraform apply

Recommended hierarchy:

  1. HCP Terraform/TFE or controlled CI runner.
  2. Dedicated deployment runner with OIDC/workload identity.
  3. Laptop apply only for sandbox/learning or documented break-glass workflows.

Applying a saved reviewed plan is safer than regenerating a plan immediately before apply when your workflow supports preserving the plan artifact securely.

terraform destroy

Treat as a destructive privileged operation. Prefer environment protection, explicit approval, and resource protection where appropriate.

terraform show

Saved plan JSON is excellent input for policy engines and scanners:

terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json

Security: plan output can contain sensitive information. Store it only in trusted, short-lived CI artifacts.

terraform state

Useful commands:

terraform state list
terraform state show aws_instance.web
terraform state mv OLD_ADDRESS NEW_ADDRESS
terraform state rm ADDRESS
Code language: CSS (css)

Policy:

  • Never directly editย terraform.tfstate.
  • Back up/retain remote state versions.
  • Require peer review/change ticket for production state surgery.
  • Prefer Terraform language mechanisms such asย movedย blocks where they solve the problem cleanly.
  • state rmย means “stop managing this object”; it does not delete the real object.

3. VS Code + HashiCorp Terraform Extension

Why

The editor should catch low-cost mistakes before you reach a terminal or CI.

The official HashiCorp extension currently provides language-server-backed:

  • syntax highlighting,
  • IntelliSense/completion,
  • inline diagnostics,
  • formatting,
  • go-to-definition and symbols,
  • module/project navigation,
  • snippets,
  • HCP Terraform workspace/run integration,
  • support for newer Terraform language surfaces.

Installation

VS Code Marketplace extension:

HashiCorp Terraform
publisher: HashiCorp

The extension bundles a compatible terraform-ls, so most VS Code users should not separately install the language server.

Recommended settings

Example .vscode/settings.json:

{
  "[terraform]": {
    "editor.defaultFormatter": "HashiCorp.terraform",
    "editor.formatOnSave": true,
    "editor.formatOnPaste": false,
    "editor.codeActionsOnSave": {
      "source.organizeImports": "never"
    }
  },
  "[terraform-vars]": {
    "editor.defaultFormatter": "HashiCorp.terraform",
    "editor.formatOnSave": true
  },
  "files.trimTrailingWhitespace": true,
  "files.insertFinalNewline": true,
  "editor.rulers": [100, 120]
}
Code language: JSON / JSON with Comments (json)

The HashiCorp extension should be the authority for Terraform formatting; avoid competing formatters for .tf.

Useful companion extensions

Keep the list small:

  • GitLens or your organization’s Git review extension.
  • YAML extension for CI/config files.
  • Markdown lint/preview for module docs.
  • EditorConfig if your organization uses it.
  • AI assistant only if approved by your security/data policy.

Avoid installing multiple Terraform format/language extensions at the same time.


4. terraform-ls

What

terraform-ls is HashiCorp’s official Terraform language server. It exposes IDE features over the Language Server Protocol.

Provides

  • completions,
  • diagnostics,
  • navigation,
  • reference awareness,
  • provider/schema intelligence,
  • module awareness,
  • workspace indexing.

Installation decision

VS Code

Do not normally install manually. The HashiCorp Terraform extension bundles the compatible server.

Other LSP-compatible editors

Manual installation can be appropriate.

macOS/Linux with Homebrew:

brew install hashicorp/tap/terraform-ls
terraform-ls version

Best practice

Open the project folder/workspace, not only one .tf file. Whole-project indexing enables better module/ref navigation.


5. Terraform MCP Server

What

Terraform MCP Server connects an MCP-capable AI client to current Terraform provider/module/policy information and, when configured, HCP Terraform/TFE context.

Problem it solves

Without external grounding, an AI model can produce:

  • provider arguments removed two versions ago,
  • fictional resources,
  • invalid nesting,
  • outdated module interfaces,
  • obsolete HCP Terraform behavior.

MCP reduces that risk by giving the agent current source context.

Architecture

Developer request
      โ†“
AI host / coding agent
      โ†“
MCP client
      โ†“
Terraform MCP Server
      โ†“
Terraform Registry / HCP Terraform
      โ†“
Current provider, module, policy, workspace context
      โ†“
AI-generated suggestion
      โ†“
fmt โ†’ validate โ†’ lint โ†’ security โ†’ test โ†’ plan
Code language: JavaScript (javascript)

Use cases

  • “Show the current schema for this AWS resource before generating it.”
  • “Find an approved module in our private registry.”
  • “Explain this provider argument using the current provider docs.”
  • “Generate a module that is compatible with our pinned provider.”
  • “Find the HCP Terraform workspace for this stack and summarize its run context.”

Example prompts

Using the Terraform MCP Server, verify the current AWS provider schema for
aws_s3_bucket and generate the smallest secure example compatible with our
required provider constraint. Do not invent attributes.
Code language: JavaScript (javascript)
Find the current Registry documentation for the module used in ./network.
Explain which inputs are required and identify any code in our wrapper that is
using removed/deprecated inputs. Do not change state addresses.
Code language: JavaScript (javascript)
Before modifying this Terraform, list the resources that would be security
sensitive (IAM, KMS, network ingress, state backend). Generate code only after
checking current provider documentation. Then run fmt/validate/test and explain
remaining assumptions.
Code language: JavaScript (javascript)

Security rules

Treat the MCP server as a privileged integration if it can access private HCP Terraform information.

  • Scope HCP tokens minimally.
  • Do not expose sensitive state to an AI tool by default.
  • Separate read/documentation use from write/run-management permissions.
  • Review generated commands before execution.
  • Never authorize autonomous production apply merely because the generated HCL validates.

Recommendation: Strongly recommended for teams already using AI-assisted Terraform, optional otherwise.


PART 3 โ€” Terraform Version Management

6. tenv

What

tenv is a Go-based version manager for Terraform, OpenTofu, Terragrunt, Terramate, and Atmos. It is the successor to tfenv/tofuenv.

Why

One globally installed Terraform version creates avoidable problems:

  • project A needs a new language feature,
  • project B is still validated on an older minor version,
  • CI and laptop silently differ,
  • developers accidentally upgrade providers/state behavior by upgrading the CLI.

Installation

macOS:

brew install tofuutils/tap/tenv

Verify:

tenv --version
tenv tf --help

Common usage

tenv tf install 1.16.0
tenv tf use 1.16.0
terraform version
Code language: CSS (css)

Project file:

# .terraform-version
1.16.0
Code language: CSS (css)

tenv can also resolve compatible Terraform versions from required_version constraints.

Team policy

For root configurations:

terraform {
  required_version = "~> 1.16.0"
}
Code language: JavaScript (javascript)

and use the same minor/patch policy in CI.

For reusable modules, avoid unnecessarily over-constraining callers. If the module only needs a feature introduced in 1.7:

terraform {
  required_version = ">= 1.7.0"
}
Code language: JavaScript (javascript)

Comparison

ToolBest fitStrengthLimitation
tenvTerraform/OpenTofu/Terragrunt-centric teamsPurpose-built, multi-IaC binary supportAnother tool to standardize
tfenvExisting Terraform-only estatesFamiliar and simpletenv is its modern successor
asdfPolyglot toolchainsOne manager for many ecosystemsPlugin lifecycle/UX
miseModern polyglot developer environmentsFast, broad tooling and task supportBroader than Terraform-specific need

Default recommendation: tenv for Terraform-centric teams; mise is an excellent choice if the organization already standardizes all developer tools through it.


PART 4 โ€” Terraform Code Quality

7. terraform fmt

Formatting is non-negotiable because it removes style arguments from review.

terraform fmt -recursive
terraform fmt -check -recursive

Local: write/fix.
CI: -check.

Do not build an internal HCL formatting standard that conflicts with terraform fmt.


8. terraform validate

Use it as a structural gate, not as a linter or security test.

CI-friendly:

terraform init -backend=false -input=false
terraform validate -no-color
Code language: JavaScript (javascript)

Use a real plan later when values/backend/provider runtime context matters.


9. TFLint

What

TFLint is a pluggable Terraform linter. Its built-in Terraform rules catch language-level issues, and cloud provider rulesets add checks that Terraform’s core validation cannot know.

Problems it solves

  • deprecated HCL patterns,
  • unused declarations,
  • missing required provider/version constraints,
  • unpinned Registry modules,
  • invalid or discouraged provider-specific values,
  • invalid instance types,
  • organization naming conventions through configured/custom rules.

Installation

macOS:

brew install terraform-linters/tap/tflint

Windows:

winget install -e --id TerraformLinters.tflint
Code language: CSS (css)

Linux: use the signed/attested release artifacts or the project’s documented installer.

Production-oriented .tflint.hcl

tflint {
  required_version = ">= 0.64.0"
}

config {
  call_module_type    = "all"
  disabled_by_default = false
}

plugin "terraform" {
  enabled = true
  preset  = "recommended"
}

plugin "aws" {
  enabled = true
  version = "0.48.0"
  source  = "github.com/terraform-linters/tflint-ruleset-aws"
}

# Useful team-level additions beyond the recommended preset.
rule "terraform_documented_variables" {
  enabled = true
}

rule "terraform_documented_outputs" {
  enabled = true
}

rule "terraform_naming_convention" {
  enabled = true
}
Code language: PHP (php)

Initialize and run:

tflint --init
tflint --recursive --format=compact

For CI systems repeatedly running tflint --init, provide an authenticated GitHub token to avoid anonymous GitHub API rate limits.

TFLint vs validate

terraform validateTFLint
Terraform-native structural validityStatic lint/best-practice checks
Understands Terraform language/module configurationExtensible provider-specific rules
Not a style/security scannerCan catch deprecated/invalid provider patterns
Mandatory baselineStrongly recommended complement

PART 5 โ€” Terraform Security

10. Trivy

What

Trivy scans Terraform/IaC for misconfiguration and can also scan repositories/filesystems for secrets and other security problems.

Common findings

  • public exposure,
  • weak encryption,
  • risky IAM,
  • permissive security groups,
  • weak storage policies,
  • Kubernetes misconfiguration,
  • plaintext secret patterns.

Commands

IaC misconfiguration:

trivy config .

Block high/critical findings:

trivy config --severity HIGH,CRITICAL --exit-code 1 .
Code language: PHP (php)

Scan repository/filesystem for both misconfiguration and secrets:

trivy fs --scanners misconfig,secret --severity HIGH,CRITICAL .

Use tfvars when appropriate:

trivy config --tf-vars environments/staging/staging.tfvars .

Policy

  • Run a fast high/critical gate locally.
  • Run the authoritative scan in CI.
  • Exceptions need a reason, owner, and preferably expiration date.
  • Treat scanner output as a risk signal, not proof of exploitability.

11. Checkov

What

Checkov is an IaC static analysis and compliance/policy scanner with Terraform source and Terraform plan scanning.

Install in an isolated Python environment:

pipx install checkov
checkov --version

Source scan:

checkov -d .

Plan scan:

terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json
checkov -f tfplan.json

Security: plan JSON may contain injected values and secrets. Create and scan it only in trusted CI and avoid publishing it as a broadly readable artifact.

Trivy vs Checkov

SituationRecommendation
Small/medium team wants one broad security toolTrivy only
Organization already standardizes Prisma/Checkov policies/complianceCheckov only can be enough
Regulated org has distinct, non-overlapping policy packs and accepts runtime costBoth, but define ownership
Same findings duplicated in both with no governance benefitRemove one

Do not add both simply to create the appearance of more security.


PART 6 โ€” Terraform Testing

12. Native terraform test

What

Terraform’s native test framework executes .tftest.hcl files with run, variables, assertions, plan/apply modes, helper modules, and provider/resource mocking.

Minimal example

main.tf:

variable "environment" {
  type = string

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "environment must be dev, staging, or prod"
  }
}

locals {
  name = "payments-${var.environment}"
}

output "name" {
  description = "Generated workload name."
  value       = local.name
}
Code language: JavaScript (javascript)

tests/name.tftest.hcl:

run "staging_name" {
  command = plan

  variables {
    environment = "staging"
  }

  assert {
    condition     = output.name == "payments-staging"
    error_message = "Unexpected generated name."
  }
}
Code language: JavaScript (javascript)

Run:

terraform test
terraform test -filter=tests/name.tftest.hcl

Provider mocking

For modules using real providers, Terraform 1.7+ can mock providers:

mock_provider "aws" {}

run "secure_bucket_configuration" {
  command = plan

  assert {
    condition     = aws_s3_bucket.example.bucket == var.bucket_name
    error_message = "Bucket name wiring is incorrect."
  }
}
Code language: JavaScript (javascript)

This is excellent for logic/interface tests without cloud credentials or real resources.

Test pyramid

            Live E2E / integration
          Terratest / custom tests
        -----------------------------
             terraform test
        plan/apply + mocks/assertions
      ---------------------------------
      validate + TFLint + security scan
    -------------------------------------
                  fmt

What each layer proves

ToolProves
validateTerraform configuration can be parsed/validated
TFLintLint/provider conventions
terraform testDeclared module behavior/assertions
Real planConcrete proposed change in target context
TerratestDeployed infrastructure actually behaves as expected

Terratest

Use when you need:

  • actual AWS/Azure/GCP API behavior,
  • HTTP/DNS/TLS checks,
  • retries/eventual consistency,
  • cross-component E2E validation,
  • deploy โ†’ validate โ†’ destroy workflows.

Costs:

  • slower,
  • cloud cost,
  • credential requirements,
  • cleanup complexity,
  • flaky external dependencies.

Default: native terraform test first; Terratest only for gaps.

Kitchen-Terraform

Still useful in teams already invested in Test Kitchen/Ruby-based infrastructure testing. It is rarely the first recommendation for a new Terraform-only test platform in 2026.


PART 7 โ€” Terraform Documentation

13. terraform-docs

What

Generates Terraform module documentation from source:

  • requirements,
  • providers,
  • modules,
  • resources,
  • inputs,
  • outputs.

Installation

macOS:

brew install terraform-docs

Usage

terraform-docs markdown table .
terraform-docs markdown table --output-file README.md --output-mode inject .
Code language: CSS (css)

README before

# VPC module

Creates a VPC.
Code language: PHP (php)

README with markers

# VPC module

Creates a VPC.

<!-- BEGIN<em>_TF_</em>DOCS -->
<!-- END<em>_TF_</em>DOCS -->
Code language: HTML, XML (xml)

After terraform-docs, the marker section contains generated Requirements, Providers, Inputs, Outputs, etc.

.terraform-docs.yml

formatter: "markdown table"

output:
  file: "README.md"
  mode: "inject"
  template: |-
    <!-- BEGIN_TF_DOCS -->
    {{ .Content }}
    <!-- END_TF_DOCS -->

sort:
  enabled: true
  by: "required"

settings:
  anchor: true
  default: true
  description: true
  escape: true
  hide-empty: false
  html: true
  lockfile: true
  read-comments: true
  required: true
  sensitive: true
  type: true
Code language: HTML, XML (xml)

Best practice

Generated interface reference is not a replacement for authored documentation. A gold-standard module README has:

  1. purpose,
  2. architecture/behavior,
  3. security assumptions,
  4. usage example,
  5. generated inputs/outputs,
  6. upgrade notes,
  7. operational caveats.

PART 8 โ€” Terraform Cost Management

14. Infracost

What

Infracost estimates cloud cost and turns Terraform changes into a cost delta visible during review.

Workflow

Terraform change
      โ†“
Plan/HCL analysis
      โ†“
Infracost
      โ†“
Monthly cost estimate + delta
      โ†“
PR reviewer sees cost impact
      โ†“
Budget / FinOps decision

CLI

infracost breakdown --path .
infracost breakdown --path . --format json --out-file infracost-base.json
infracost diff --path . --compare-to infracost-base.json
Code language: CSS (css)

It can also consume Terraform plan JSON when source parsing is not sufficient.

CI recommendation

For GitHub, prefer the vendor’s current GitHub App or modern diff/scan actions where allowed. Avoid building new integrations around legacy action patterns unless you need the lower-level CLI.

Policy

Cost estimation is advisory unless your organization has explicitly defined budgets/thresholds. A small cost increase may be correct; a zero-cost plan may still be dangerously destructive.


PART 9 โ€” Git Automation

15. pre-commit-terraform

Why high value

It moves deterministic checks left:

git commit
    โ†“
fmt
    โ†“
validate
    โ†“
TFLint
    โ†“
Trivy
    โ†“
terraform-docs
    โ†“
commit accepted

Installation

brew install pre-commit
<em># or</em>
pipx install pre-commit

pre-commit --version
Code language: HTML, XML (xml)

Production-ready .pre-commit-config.yaml

repos:
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.108.1
    hooks:
      - id: terraform_fmt

      - id: terraform_validate
        args:
          - --hook-config=--retry-once-with-cleanup=true

      - id: terraform_tflint

      - id: terraform_trivy
        args:
          - --args=--severity=HIGH,CRITICAL
          - --args=--exit-code=1

      - id: terraform_docs
Code language: JavaScript (javascript)

Enable:

pre-commit install
pre-commit run --all-files

Local vs CI split

Local

Run checks that are fast and deterministic:

  • fmt,
  • validate,
  • TFLint,
  • focused Trivy,
  • docs.

CI

Re-run them authoritatively and add:

  • full security policy,
  • terraform test,
  • target-context plan,
  • Infracost,
  • plan-policy checks,
  • approval/apply rules.

Never rely solely on local hooks; users can skip them and environments differ.


PART 10 โ€” Terraform Project Structure

16. Recommended repository layout

For a moderate monorepo:

terraform/
โ”œโ”€โ”€ modules/
โ”‚   โ”œโ”€โ”€ vpc/
โ”‚   โ”‚   โ”œโ”€โ”€ main.tf
โ”‚   โ”‚   โ”œโ”€โ”€ variables.tf
โ”‚   โ”‚   โ”œโ”€โ”€ outputs.tf
โ”‚   โ”‚   โ”œโ”€โ”€ versions.tf
โ”‚   โ”‚   โ”œโ”€โ”€ tests/
โ”‚   โ”‚   โ””โ”€โ”€ README.md
โ”‚   โ”œโ”€โ”€ eks/
โ”‚   โ”œโ”€โ”€ rds/
โ”‚   โ””โ”€โ”€ iam/
โ”‚
โ”œโ”€โ”€ environments/
โ”‚   โ”œโ”€โ”€ development/
โ”‚   โ”œโ”€โ”€ staging/
โ”‚   โ””โ”€โ”€ production/
โ”‚
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ workflows/
โ”œโ”€โ”€ .pre-commit-config.yaml
โ”œโ”€โ”€ .tflint.hcl
โ”œโ”€โ”€ renovate.json
โ””โ”€โ”€ README.md

Root module vs child module

Root module: deployment unit. Owns backend, environment composition, concrete provider constraints, and state.

Child/reusable module: abstraction with documented inputs/outputs. It should not normally own a backend or assume one environment/account.

Files

Recommended per module:

main.tf        # primary resources/module calls
variables.tf   # inputs
outputs.tf     # outputs
versions.tf    # Terraform/provider requirements
locals.tf      # optional, when locals warrant separation
data.tf        # optional
tests/         # native tests
README.md
Code language: PHP (php)

Split further by domain only when it improves readability; Terraform loads all .tf files in the directory together.

Environment separation

Prefer separate state per meaningful failure/ownership boundary:

production/network
production/cluster
production/database
production/app-platform

rather than one giant production state.

Reasons:

  • smaller blast radius,
  • simpler permissions,
  • faster plan,
  • clearer ownership,
  • fewer unrelated lock conflicts.

Repository strategy

StrategyProsConsBest fit
MonorepoShared standards, atomic changes, discoveryCI/path complexity, repo scaleCentral platform teams
Multi-repo by systemStrong ownership boundariesCross-repo upgrades harderIndependent teams
One repo per environmentStrong isolationDuplication/drift riskStrict org separation
One repo per reusable moduleIndependent versioning/releaseMany reposMature internal module ecosystem

There is no universal “one repo per environment” rule. Choose boundaries from ownership, release cadence, permissions, and blast radius.


PART 11 โ€” Terragrunt

17. Terragrunt

Why it exists

Terragrunt wraps Terraform/OpenTofu to reduce repetition and orchestrate many related root modules.

Common value:

  • shared remote-state configuration,
  • generated provider configuration,
  • reusable environment/account configuration,
  • dependency outputs,
  • multi-account/multi-region layouts,
  • ordered execution across units.

Current CLI model

Modern Terragrunt 1.x:

terragrunt plan
terragrunt apply
terragrunt run --all plan
terragrunt run --all apply

Do not teach new teams to standardize on legacy run-all.

Example

live/
โ”œโ”€โ”€ root.hcl
โ”œโ”€โ”€ dev/
โ”‚   โ”œโ”€โ”€ vpc/terragrunt.hcl
โ”‚   โ””โ”€โ”€ app/terragrunt.hcl
โ””โ”€โ”€ prod/
    โ”œโ”€โ”€ vpc/terragrunt.hcl
    โ””โ”€โ”€ app/terragrunt.hcl

root.hcl:

remote_state {
  backend = "s3"

  config = {
    bucket       = "example-terraform-state"
    key          = "${path_relative_to_include()}/terraform.tfstate"
    region       = "ap-northeast-1"
    encrypt      = true
    use_lockfile = true
  }
}

generate "provider" {
  path      = "provider.generated.tf"
  if_exists = "overwrite_terragrunt"

  contents = <<EOF
provider "aws" {
  region = "ap-northeast-1"
}
EOF
}
Code language: JavaScript (javascript)

prod/app/terragrunt.hcl:

include "root" {
  path = find_in_parent_folders("root.hcl")
}

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

dependency "vpc" {
  config_path = "../vpc"
}

inputs = {
  vpc_id = dependency.vpc.outputs.vpc_id
}
Code language: PHP (php)

When Terragrunt is unnecessary

Do not add it when:

  • you have a few simple root modules,
  • HCP Terraform already removes the orchestration pain you were trying to solve,
  • duplication is small and explicit,
  • the team does not need multi-unit orchestration,
  • introducing a second language/workflow would cost more than it saves.

Terraform alone is a valid production architecture.


PART 12 โ€” CI/CD

18. GitHub Actions

Pipeline architecture

Pull request
   โ†“
checkout
   โ†“
setup pinned Terraform
   โ†“
fmt -check
   โ†“
init -backend=false (static/test jobs)
   โ†“
validate
   โ†“
TFLint
   โ†“
Trivy
   โ†“
terraform test
   โ†“
OIDC โ†’ target read/plan role
   โ†“
terraform init
   โ†“
terraform plan
   โ†“
Infracost / policy / review
Code language: JavaScript (javascript)

Apply should be a separate controlled phase, not an automatic side effect of every PR plan.

Example CI workflow

name: terraform-ci

on:
  pull_request:
    paths:
      - "**/*.tf"
      - "**/*.tfvars"
      - "**/*.tftest.hcl"
      - ".github/workflows/terraform-ci.yml"

permissions:
  contents: read

jobs:
  quality:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.16.0"
          terraform_wrapper: false

      - name: Format
        run: terraform fmt -check -recursive

      - name: Init without backend
        run: terraform init -backend=false -input=false

      - name: Validate
        run: terraform validate -no-color

      - name: Setup TFLint
        uses: terraform-linters/setup-tflint@v6
        with:
          tflint_version: "v0.64.0"
          cache: true

      - name: Init TFLint plugins
        run: tflint --init
        env:
          GITHUB_TOKEN: ${{ github.token }}

      - name: TFLint
        run: tflint --recursive --format=compact

      - name: Trivy IaC
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: config
          scan-ref: .
          severity: HIGH,CRITICAL
          exit-code: "1"

      - name: Terraform tests
        run: terraform test
Code language: PHP (php)

Supply-chain hardening note

For a true enterprise workflow, pin reusable GitHub Actions to reviewed immutable commit SHAs or enforce an organization action allowlist. Major tags are easier to read in a handbook but are mutable references.

Plan job with AWS OIDC

  plan:
    needs: quality
    runs-on: ubuntu-latest

    permissions:
      contents: read
      id-token: write

    environment: staging

    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.16.0"
          terraform_wrapper: false

      - name: Authenticate to AWS using OIDC
        uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: arn:aws:iam::123456789012:role/terraform-staging-plan
          aws-region: ap-northeast-1

      - name: Init
        working-directory: environments/staging
        run: terraform init -input=false

      - name: Plan
        working-directory: environments/staging
        run: terraform plan -input=false -no-color

OIDC design

Trust should be constrained by claims such as:

  • organization/repository identity,
  • environment,
  • branch/tag,
  • immutable repository/org IDs where supported.

The plan role and apply role should be separate when practical.

Apply model

Recommended:

PR merged to protected branch
       โ†“
new plan in controlled execution context
       โ†“
policy checks
       โ†“
environment approval
       โ†“
assume apply role using OIDC
       โ†“
terraform apply
       โ†“
verification
Code language: PHP (php)

Why re-plan after merge? The reviewed branch may no longer be identical to the final protected branch if multiple changes merged.

If your system securely preserves a reviewed saved plan and guarantees code/state identity, applying the preserved plan is also valid.

Secrets

Never store:

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
long-lived Azure client secrets
long-lived GCP service-account JSON
Code language: JavaScript (javascript)

when federation is available.


19. GitLab CI

Use the same gates:

validate โ†’ lint โ†’ security โ†’ test โ†’ plan โ†’ policy โ†’ approval โ†’ apply

GitLab supports OIDC ID tokens for cloud federation. Modern GitLab uses ID tokens, not the removed legacy CI_JOB_JWT_V2.

Illustrative shape:

stages:
  - quality
  - plan
  - apply

terraform-quality:
  stage: quality
  image: hashicorp/terraform:1.16.0
  script:
    - terraform fmt -check -recursive
    - terraform init -backend=false -input=false
    - terraform validate
    - terraform test

terraform-plan:
  stage: plan
  id_tokens:
    GITLAB_OIDC_TOKEN:
      aud: sts.amazonaws.com
  script:
    - echo "Exchange GitLab OIDC token for short-lived cloud credentials"
    - terraform init -input=false
    - terraform plan -input=false

terraform-apply:
  stage: apply
  when: manual
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
  script:
    - terraform apply -input=false
Code language: PHP (php)

Exact AWS/Azure/GCP token-exchange steps should follow the current cloud/GitLab federation documentation and your organization’s role design.


PART 13 โ€” Atlantis

20. Atlantis

What

Atlantis is a server that reacts to pull-request comments/events and runs Terraform plans/applies in a PR-driven workflow.

PR opened
   โ†“
Atlantis autoplan
   โ†“
review plan
   โ†“
approval
   โ†“
atlantis apply

Commands

atlantis plan
atlantis apply

Strengths

  • PR-native workflow,
  • project/workspace awareness,
  • locking,
  • plan/apply conversation in VCS,
  • works across multiple Terraform projects.

Atlantis locks a directory/workspace when a plan is active so competing PRs do not casually race the same deployment unit.

Atlantis vs GitHub Actions vs HCP Terraform

NeedBetter fit
Generic build/test ecosystemGitHub/GitLab CI
Comment-driven Terraform workflow you operateAtlantis
Managed state, remote runs, RBAC, registry, run tasks, policy, healthHCP Terraform
Self-hosted HCP feature setTerraform Enterprise

Avoid running Atlantis and a separate CI apply system against the same state without a very explicit ownership model.


PART 14 โ€” HCP Terraform

21. HCP Terraform

What it adds beyond CLI

  • remote state and state history,
  • stronger centralized run coordination,
  • remote runs,
  • workspaces,
  • projects,
  • variable sets,
  • self-hosted agents,
  • private module/provider registry,
  • run tasks,
  • policy enforcement,
  • VCS-driven speculative plans,
  • team/project/workspace RBAC,
  • health assessments including drift detection and continuous validation,
  • API/audit capabilities depending on edition.

Enterprise workflow

Git branch
   โ†“
Pull request
   โ†“
HCP speculative plan
   โ†“
CI/security/cost checks
   โ†“
review
   โ†“
merge
   โ†“
HCP run
   โ†“
policy checks / run tasks
   โ†“
approval
   โ†“
remote worker or private agent
   โ†“
cloud
   โ†“
health assessment / drift detection
Code language: PHP (php)

Workspaces

An HCP Terraform workspace is a deployment/state boundary, not the same concept as a Terraform CLI workspace.

Use workspaces to separate infrastructure with different:

  • state,
  • permissions,
  • ownership,
  • credentials,
  • run cadence,
  • blast radius.

Avoid a single giant workspace for an entire company environment.

Projects

Use projects as access-control/organizational boundaries grouping workspaces and Stacks.

Good project boundaries:

  • platform,
  • analytics,
  • security,
  • business unit,
  • account/portfolio.

Variable sets

Good uses:

  • common non-secret environment settings,
  • dynamic credential configuration,
  • shared provider settings,
  • organization/project-wide standards.

Do not use variable sets as an excuse to hide every important deployment value from code review.

Agents

Use HCP Terraform Agents when the run must reach:

  • private VPC/VNet resources,
  • on-premises services,
  • private APIs,
  • network-isolated providers.

Agents need only outbound connectivity to HCP Terraform.

Do not deploy agents merely because “enterprise teams use agents.” Built-in workers are simpler when private network access/custom tooling is not required.

Private registry

Use the private registry for:

  • approved reusable modules,
  • internally developed providers,
  • versioned organization patterns.

A mature platform team should make the secure path the easy path:

developer need โ†’ approved private module โ†’ small set of inputs โ†’ tests/policy โ†’ deploy
Code language: JavaScript (javascript)

Run tasks

Useful for third-party checks at lifecycle stages such as:

  • pre-plan,
  • post-plan,
  • pre-apply,
  • post-apply.

Examples:

  • security platform,
  • cost governance,
  • custom compliance,
  • image validation.

Only integrate trusted run-task services because run-related information can be sensitive.

HCP Terraform vs Terraform Enterprise vs CLI

CapabilityTerraform CLIHCP TerraformTerraform Enterprise
Terraform engineYesYesYes
Local executionYesCan integrateCan integrate
Managed SaaSNoYesNo
Self-hosted platformNoNoYes
Remote stateVia backendBuilt inBuilt in
Remote runsNo platform by itselfBuilt inBuilt in
Projects/RBACNoYesYes
Private registryNoYesYes
AgentsN/AYesYes
Policy/run tasksExternalIntegratedIntegrated
Drift/healthExternalIntegrated by editionIntegrated

Terraform Enterprise is the self-hosted distribution of the HCP Terraform application for organizations requiring private hosting/advanced architecture/compliance controls.


PART 15 โ€” Policy as Code

22. Sentinel

What

HashiCorp’s policy-as-code framework integrated with HCP Terraform/TFE.

Enforcement styles

  • Advisoryย โ€” report failure but allow run.
  • Soft mandatory / overridableย โ€” block unless authorized override.
  • Hard mandatory / mandatoryย โ€” block until fixed, subject to platform policy-set semantics.

Use terms carefully because HCP Terraform’s UI/framework-specific naming can differ.

Example policy scenarios

  • approved AWS regions,
  • no public storage,
  • allowed EC2 families,
  • mandatory tags,
  • encryption required,
  • restrict resource deletion,
  • only approved modules.

Rollout model

new rule
  โ†“
advisory
  โ†“
observe false positives
  โ†“
fix existing estate
  โ†“
mandatory with controlled exception process
Code language: JavaScript (javascript)

Do not deploy dozens of untested hard-blocking policies on day one.


23. OPA / Conftest

OPA

OPA evaluates Rego policies against structured input. Terraform plan JSON is a common input:

terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
opa exec --decision terraform/analysis/authz --bundle policy/ tfplan.json

Caveat: plan-time unknown values can limit what a policy can know.

Conftest

Conftest is a convenient CLI for executing Rego checks against structured files.

conftest test tfplan.json --policy policy/
conftest verify --policy policy/

Typical policy:

package main

deny contains msg if {
  some rc in input.resource_changes
  rc.type == "aws_security_group_rule"
  some cidr in rc.change.after.cidr_blocks
  cidr == "0.0.0.0/0"
  msg := sprintf("Public ingress is not allowed: %s", [rc.address])
}
Code language: JavaScript (javascript)

Production policies need careful handling for null/unknown/alternate resource shapes; the snippet is intentionally small.

Decision guide

FrameworkBest fit
Terraform Policy (HCL)Terraform-centric HCP teams wanting native HCL policy; evaluate maturity while beta
SentinelHCP/TFE estates with HashiCorp governance investment
OPAVendor-neutral enterprise policy platform
ConftestLightweight local/CI Rego execution

PART 16 โ€” Dependency Management

24. Renovate

What

Automates dependency update PRs for:

  • Terraformย required_version,
  • .terraform-version,
  • providers,
  • Registry modules,
  • Git-based modules where supported,
  • GitHub Actions,
  • many surrounding build dependencies.

Recommended renovate.json

{
  "extends": ["config:recommended"],
  "labels": ["dependencies"],
  "packageRules": [
    {
      "matchManagers": ["terraform", "terraform-version"],
      "groupName": "terraform dependencies",
      "schedule": ["before 6am on monday"]
    },
    {
      "matchManagers": ["github-actions"],
      "groupName": "github actions"
    },
    {
      "matchUpdateTypes": ["major"],
      "dependencyDashboardApproval": true
    }
  ]
}
Code language: JSON / JSON with Comments (json)

Upgrade policy

Do not auto-merge major Terraform/provider/module upgrades into production infrastructure merely because CI is green.

Recommended:

patch โ†’ may auto-merge after strong test gates
minor โ†’ normal PR review
major โ†’ explicit upgrade issue, changelog review, staged rollout

25. tfupdate

tfupdate is a focused utility for rewriting Terraform/OpenTofu core/provider/module version constraints and lock files.

Example:

tfupdate terraform -v 1.16.0 -r .
tfupdate provider aws -v "~> 6.0" -r .
Code language: CSS (css)

It is still useful for scripts and specialized bulk updates.

Default recommendation: prefer Renovate for continuous dependency management because it covers Terraform, modules, providers, actions, and many other dependencies with PR workflows. Use tfupdate when you specifically need command-line rewriting/automation.


PART 17 โ€” Terraform Console

26. terraform console

The console is one of the fastest ways to debug Terraform expressions without creating resources.

terraform console
Code language: JavaScript (javascript)

Examples:

> upper("prod")
"PROD"

> length(["a", "b", "c"])
3

> contains(["dev", "prod"], "prod")
true

> merge({a = 1}, {b = 2})
{
  "a" = 1
  "b" = 2
}

> [for x in ["api", "worker"] : "prod-${x}"]
[
  "prod-api",
  "prod-worker",
]

> { for x in ["api", "worker"] : x => upper(x) }
{
  "api" = "API"
  "worker" = "WORKER"
}

> cidrsubnet("10.0.0.0/16", 8, 1)
"10.0.1.0/24"

> try({a = 1}.b, "fallback")
"fallback"
Code language: JavaScript (javascript)

Use it to prototype:

  • forย expressions,
  • map merging,
  • conditionals,
  • CIDR subdivision,
  • string transformations,
  • try/can,
  • regex,
  • collection conversion.

Do not use console output as a substitute for a repeatable test when the expression matters to production behavior.


PART 18 โ€” IDE + AI Development Workflow

27. Modern AI-assisted workflow

Developer intent
      โ†“
AI agent
      โ†“
Terraform MCP / current provider docs
      โ†“
Generate/refactor HCL
      โ†“
terraform fmt
      โ†“
terraform validate
      โ†“
TFLint
      โ†“
Trivy
      โ†“
terraform test
      โ†“
human review
      โ†“
real plan

Good AI tasks

  • generate boilerplate,
  • explain resources,
  • draft variables/outputs,
  • create native tests,
  • refactor repeated HCL,
  • produce module documentation,
  • identify likely missing validation,
  • compare plan output,
  • search current provider docs through MCP.

Never blindly trust AI for

  • IAM,
  • security-group/network exposure,
  • KMS/key policy,
  • destructive lifecycle changes,
  • provider upgrade compatibility,
  • terraform stateย operations,
  • imports/moves without address review,
  • production apply,
  • secret handling,
  • cost assumptions.

AI prompt template

Act as a senior Terraform reviewer.

Context:
- Terraform: <constraint>
- Provider: <source + constraint>
- Execution: <HCP Terraform / CI / local>
- Environment: <dev/stage/prod>
- State boundary: <description>

Task:
<requested change>

Before writing code:
1. Use current Terraform/provider documentation or Terraform MCP.
2. Identify security, state, replacement, and cost risks.
3. Preserve resource addresses unless a move is explicitly required.
4. Do not hardcode credentials/secrets.
5. Prefer OIDC/workload identity.

After writing code:
1. terraform fmt
2. terraform validate
3. TFLint
4. Trivy
5. terraform test
6. explain expected plan and anything requiring human verification.

Never run or recommend an unreviewed production apply.
Code language: HTML, XML (xml)

PART 19 โ€” Terraform Developer Daily Workflow

28. Daily workflow

  1. Pull latest codegit switch main git pull --ff-only
  2. Select project tool versiontenv tf install terraform version
  3. Create a branchgit switch -c feat/add-private-endpoint
  4. Initializeterraform init
  5. Write/change Terraform
  6. Formatterraform fmt -recursive
  7. Validateterraform validate
  8. Linttflint --init tflint --recursive
  9. Security scantrivy config --severity HIGH,CRITICAL --exit-code 1 .
  10. Run teststerraform test
  11. Generate docsterraform-docs markdown table --output-file README.md --output-mode inject .
  12. Plan in a safe target contextterraform plan
  13. Inspect cost deltainfracost breakdown --path .
  14. Review your own diffgit diff git status
  15. Commitgit add . git commit -m "feat: add private endpoint"
  16. Pre-commit hooks execute
  17. Pushgit push -u origin HEAD
  18. CI reproduces checks and plan
  19. PR reviewย Reviewer checks security, replacement, blast radius, cost, test quality.
  20. Policy validation
  21. Controlled apply
  22. Post-deployment verificationย Check service health, metrics, logs, connectivity, and expected outputs.
  23. Drift/health feedbackย Operational system closes the loop.

PART 20 โ€” Complete Developer Toolchain Reference

29. Master reference

ToolProblem solvedBasic usageValueLimitationClassification
Terraform CLIIaC lifecycleterraform planCore engineNeeds surrounding controlsMUST
VS CodeAuthoringopen projectProductivityEditor onlyRecommended
HashiCorp extensionTerraform IDEinstall extensionCompletion/diagnosticsVS Code focusedRecommended
terraform-lsLSP intelligencenormally bundledSchema/navigationNot security/policyRecommended
Terraform MCPAI current contextconfigure MCP hostReduces stale AI outputTrust/access designRecommended with AI
tenvBinary versionstenv tf useReproducibilityExtra dependencyRecommended
terraform fmtStylefmt -recursiveDeterministic formatNot validationMUST
terraform validateConfig validityvalidateCheap errorsNot provider runtime securityMUST
TFLintLint/provider checkstflint --recursiveHigher code qualityNot full securityRecommended
TrivyMisconfig/secretstrivy config .Broad securityPolicy noise possibleRecommended
CheckovCompliance/IaC policycheckov -d .Broad policy libraryOverlapOptional
terraform testNative behavior teststerraform testFast/nativeLive behavior may need moreRecommended
TerratestReal integration testsgo testStrong E2ESlow/cost/flakinessOptional
terraform-docsInterface docsterraform-docs ...No stale input/output tablesDoesn’t write architecture narrativeRecommended
InfracostCost deltainfracost diffFinOps in reviewEstimate not invoiceRecommended
pre-commit-terraformLocal gatespre-commit runFast feedbackCan be bypassedRecommended
GitVersion/reviewgit diffAudit/reviewNeeds policyMUST
GitHub/GitLabCollaborationPR/MRReview controlsPlatform dependencyMUST for teams
GitHub Actions/GitLab CIAutomationpipelineReproducible checksRunner/security design neededMUST for prod teams
TerragruntMulti-unit DRY/orchestrationrun --all planScale multi-env layoutsAdded abstractionOptional
AtlantisPR-driven TerraformPR commandsTerraform-focused UXOperate server/securityOptional
HCP TerraformRemote Terraform platformworkspace runsState/runs/RBAC/policyCommercial/platform choiceRecommended/Enterprise
Terraform EnterpriseSelf-hosted HCPself-hostCompliance/private hostingOperational burdenEnterprise
SentinelHCP/TFE policypolicy setsIntegrated governanceHashiCorp-specificEnterprise
OPAVendor-neutral policyopa execReusable policy platformRego learning curveEnterprise/Optional
ConftestRego CLIconftest testEasy CI integrationNot Terraform orchestratorOptional
RenovateDependency PRsbot/appSustainable upgradesNeeds grouping/rulesRecommended
tfupdateConstraint rewritestfupdate providerFocused automationNarrower than RenovateOptional

PART 21 โ€” Recommended Stacks by Maturity

30. Beginner

Terraform CLI
VS Code
HashiCorp Terraform Extension
terraform fmt
terraform validate
Git

Add a remote backend once working with others.

31. Professional developer

Terraform CLI
VS Code + terraform-ls
tenv
TFLint
Trivy
terraform test
terraform-docs
pre-commit-terraform
GitHub/GitLab CI
remote state + locking
OIDC

32. Senior / Platform engineer

Everything above
Terraform MCP Server
Infracost
reusable module standards
Renovate
structured state boundaries
policy tests
controlled runners
HCP Terraform where appropriate
Terragrunt only if complexity justifies it
Code language: JavaScript (javascript)

33. Enterprise platform

approved IDE/toolchain
private module/provider registry
central CI templates
OIDC/workload identity
remote execution
HCP Terraform/TFE
private agents where needed
RBAC
run tasks
policy-as-code
cost governance
audit logs
drift/health assessments
dependency automation
AI/MCP governance
Code language: PHP (php)

PART 22 โ€” Gold Standard Terraform Pipeline

34. Pipeline

Developer
   โ†“
IDE
   โ†“
AI/MCP assistance
   โ†“
Terraform code
   โ†“
Format
   โ†“
Validate
   โ†“
Lint
   โ†“
Security scan
   โ†“
Native tests
   โ†“
Documentation
   โ†“
Pre-commit
   โ†“
Push
   โ†“
CI reproduces gates
   โ†“
OIDC authentication
   โ†“
Terraform plan
   โ†“
Cost analysis
   โ†“
Policy validation
   โ†“
Code review
   โ†“
Approval
   โ†“
Controlled apply
   โ†“
Post-deploy verification
   โ†“
Monitoring / drift / continuous validation

Quality gates

GateFailure means
FormatCode not canonical
ValidateTerraform config invalid
TFLintQuality/provider rule violation
SecurityRisk exceeds accepted threshold
TestContract/behavior regression
DocsModule API reference stale
PlanChange differs from developer intent
CostMaterial unexpected spend
PolicyOrganization rule violated
ReviewHuman risk/architecture concerns
ApprovalProduction change not authorized
VerifyDeployment outcome not healthy

PART 23 โ€” Local Development Setup

35. macOS

Homebrew-centered setup:

brew tap hashicorp/tap

brew install hashicorp/tap/terraform
brew install hashicorp/tap/terraform-ls
brew install tofuutils/tap/tenv
brew install terraform-linters/tap/tflint
brew install trivy
brew install terraform-docs
brew install infracost
brew install pre-commit
brew install opa
brew install conftest

For Checkov:

brew install pipx
pipx ensurepath
pipx install checkov

You may omit manual terraform-ls if VS Code’s HashiCorp extension is your only LSP client.

Verify:

terraform version
tenv --version
tflint --version
trivy --version
terraform-docs --version
infracost --version
pre-commit --version
opa version
conftest --version
checkov --version

36. Linux

Prefer official/vendor repositories or verified release artifacts rather than random curl-pipe-shell snippets.

Example base packages:

sudo apt-get update
sudo apt-get install -y git curl unzip jq pipx
Code language: JavaScript (javascript)

Then install:

  • Terraform from HashiCorp’s official package repository,
  • TFLint from verified GitHub release artifacts,
  • Trivy from Aqua’s official package repository,
  • terraform-docs,ย tenv, OPA, Conftest from official releases,
  • Checkov withย pipx install checkov,
  • pre-commit with OS package manager or pipx.

Keep installation logic in a reproducible developer bootstrap script or dev-container image.

37. Windows

Good choices:

  • wingetย where the project publishes a verified package,
  • Chocolatey in organizations already managing it,
  • official signed release archives.

Known example:

winget install -e --id TerraformLinters.tflint
Code language: CSS (css)

Terraform itself can be installed via your organization’s package-management standard or HashiCorp’s official release archive.

Prefer WSL only if your team’s Terraform workflow intentionally standardizes on Linux semantics; do not require it just because Terraform can run there.

Setup checklist

[ ] Git
[ ] Terraform version manager
[ ] Pinned Terraform
[ ] Editor + HashiCorp Terraform extension
[ ] TFLint
[ ] Trivy
[ ] terraform-docs
[ ] pre-commit
[ ] Infracost if used
[ ] Checkov if selected
[ ] OPA/Conftest if selected
[ ] Cloud CLI
[ ] SSO/OIDC-compatible developer authentication
[ ] No long-lived cloud key in shell profile
[ ] Project hooks installed

PART 24 โ€” Sample Real AWS Project

38. Directory

aws-web/
โ”œโ”€โ”€ backend.tf
โ”œโ”€โ”€ versions.tf
โ”œโ”€โ”€ provider.tf
โ”œโ”€โ”€ variables.tf
โ”œโ”€โ”€ main.tf
โ”œโ”€โ”€ outputs.tf
โ”œโ”€โ”€ terraform.tfvars.example
โ”œโ”€โ”€ backend.hcl.example
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ basic.tftest.hcl
โ”œโ”€โ”€ .tflint.hcl
โ”œโ”€โ”€ .terraform-docs.yml
โ”œโ”€โ”€ .pre-commit-config.yaml
โ”œโ”€โ”€ .gitignore
โ””โ”€โ”€ README.md

versions.tf

terraform {
  required_version = "~> 1.16.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}
Code language: JavaScript (javascript)

backend.tf

terraform {
  backend "s3" {}
}
Code language: JavaScript (javascript)

backend.hcl.example

bucket       = "REPLACE-ME-terraform-state"
key          = "examples/aws-web/terraform.tfstate"
region       = "ap-northeast-1"
encrypt      = true
use_lockfile = true
Code language: JavaScript (javascript)

Initialize:

cp backend.hcl.example backend.hcl
<em># edit backend.hcl for your non-secret account settings</em>
terraform init -backend-config=backend.hcl
Code language: HTML, XML (xml)

Do not put access keys in backend config.

provider.tf

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      ManagedBy   = "Terraform"
      Project     = var.project_name
      Environment = var.environment
    }
  }
}
Code language: JavaScript (javascript)

Authentication comes from the AWS SDK credential chain: SSO/profile locally, OIDC/workload identity in CI.

variables.tf

variable "aws_region" {
  description = "AWS region for this deployment."
  type        = string
  default     = "ap-northeast-1"
}

variable "project_name" {
  description = "Short project identifier."
  type        = string
  default     = "tf-web"
}

variable "environment" {
  description = "Deployment environment."
  type        = string

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "environment must be dev, staging, or prod."
  }
}

variable "vpc_cidr" {
  description = "CIDR for the VPC."
  type        = string
  default     = "10.42.0.0/16"
}

variable "azs" {
  description = "Availability Zones for public subnets."
  type        = list(string)
  default     = ["ap-northeast-1a", "ap-northeast-1c"]

  validation {
    condition     = length(var.azs) == 2
    error_message = "This example expects exactly two AZs."
  }
}

variable "public_subnet_cidrs" {
  description = "CIDRs for public subnets, one per AZ."
  type        = list(string)
  default     = ["10.42.1.0/24", "10.42.2.0/24"]

  validation {
    condition     = length(var.public_subnet_cidrs) == 2
    error_message = "This example expects exactly two public subnet CIDRs."
  }
}

variable "ami_id" {
  description = "Approved AMI ID for the EC2 instance."
  type        = string
}

variable "instance_type" {
  description = "EC2 instance type."
  type        = string
  default     = "t3.micro"
}

variable "allowed_http_cidrs" {
  description = "CIDRs permitted to access TCP/80. Do not use 0.0.0.0/0 unless public exposure is intended and approved."
  type        = list(string)
}
Code language: PHP (php)

main.tf

locals {
  subnet_map = {
    for idx, az in var.azs :
    az => var.public_subnet_cidrs[idx]
  }
}

resource "aws_vpc" "this" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.project_name}-${var.environment}"
  }
}

resource "aws_internet_gateway" "this" {
  vpc_id = aws_vpc.this.id

  tags = {
    Name = "${var.project_name}-${var.environment}"
  }
}

resource "aws_subnet" "public" {
  for_each = local.subnet_map

  vpc_id                  = aws_vpc.this.id
  availability_zone       = each.key
  cidr_block              = each.value
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project_name}-${var.environment}-${each.key}"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.this.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.this.id
  }

  tags = {
    Name = "${var.project_name}-${var.environment}-public"
  }
}

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_security_group" "web" {
  name_prefix = "${var.project_name}-${var.environment}-web-"
  description = "HTTP access for example web instance"
  vpc_id      = aws_vpc.this.id

  ingress {
    description = "Approved HTTP clients"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = var.allowed_http_cidrs
  }

  egress {
    description = "Outbound access"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  ami                         = var.ami_id
  instance_type               = var.instance_type
  subnet_id                   = values(aws_subnet.public)[0].id
  vpc_security_group_ids      = [aws_security_group.web.id]
  associate_public_ip_address = true

  metadata_options {
    http_endpoint = "enabled"
    http_tokens   = "required"
  }

  root_block_device {
    encrypted = true
  }

  tags = {
    Name = "${var.project_name}-${var.environment}-web"
  }
}
Code language: PHP (php)

This deliberately exposes no SSH port. In a production design, use SSM/session tooling or another approved administration path rather than opening port 22 globally.

outputs.tf

output "vpc_id" {
  description = "VPC ID."
  value       = aws_vpc.this.id
}

output "public_subnet_ids" {
  description = "Public subnet IDs keyed by availability zone."
  value       = { for az, subnet in aws_subnet.public : az => subnet.id }
}

output "instance_id" {
  description = "EC2 instance ID."
  value       = aws_instance.web.id
}

output "public_ip" {
  description = "Public IPv4 address of the example instance."
  value       = aws_instance.web.public_ip
}
Code language: JavaScript (javascript)

terraform.tfvars.example

environment        = "dev"
ami_id             = "ami-REPLACE-WITH-AN-APPROVED-AMI"
allowed_http_cidrs = ["203.0.113.0/24"]
Code language: JavaScript (javascript)

tests/basic.tftest.hcl

mock_provider "aws" {}

run "basic_plan" {
  command = plan

  variables {
    environment        = "dev"
    ami_id             = "ami-0123456789abcdef0"
    allowed_http_cidrs = ["203.0.113.0/24"]
  }

  assert {
    condition     = aws_vpc.this.cidr_block == "10.42.0.0/16"
    error_message = "Unexpected VPC CIDR."
  }

  assert {
    condition     = length(aws_subnet.public) == 2
    error_message = "Expected two public subnets."
  }

  assert {
    condition     = aws_instance.web.metadata_options[0].http_tokens == "required"
    error_message = "IMDSv2 must be required."
  }

  assert {
    condition     = aws_instance.web.root_block_device[0].encrypted == true
    error_message = "Root volume must be encrypted."
  }
}
Code language: PHP (php)

.gitignore

.terraform/
*.tfstate
*.tfstate.*
*.tfplan
tfplan*
crash.log
crash.*.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
backend.hcl
*.auto.tfvars

Do commit:

.terraform.lock.hcl
Terraform source
non-secret examples
tests
tool configuration
Code language: CSS (css)

Run locally

terraform init -backend=false
terraform fmt -recursive
terraform validate
tflint --init
tflint --recursive
trivy config --severity HIGH,CRITICAL .
terraform test
Code language: JavaScript (javascript)

For a real plan, authenticate through AWS SSO/profile and initialize the real backend:

terraform init -backend-config=backend.hcl
terraform plan -var-file=terraform.tfvars
Code language: JavaScript (javascript)

PART 25 โ€” Common Developer Mistakes

39. Mistakes and correct alternatives

MistakeWhy dangerousCorrect alternative
Hardcoded cloud keysCredential leak/rotation burdenOIDC, SSO, workload identity
Hardcoded secretsHCL/plan/state leakSecret manager + ephemeral/write-only features where provider supports
Commit .tfstateSecrets + no safe state lockingRemote state
Commit .terraform/Large, platform-specific, unreviewableRe-run init
Ignore .terraform.lock.hclProvider driftCommit root lock file
No provider constraintsUnexpected upgradesDeclare constraints
No module versionsModule driftPin Registry module versions
Apply from laptopsWeak audit/reproducibilityControlled runner
No reviewHigh blast radiusProtected PR flow
No lint/security testsPreventable defectsAutomated gates
One giant stateHuge blast radius/lock contentionDecompose by ownership/failure boundary
Overuse CLI workspacesHidden environment couplingSeparate roots/states/workspaces where environments differ
Huge root moduleSlow/unowned/unreviewableCompose smaller deployment units
Copy/paste infrastructureDriftReusable modules/templates where repetition is stable
Weak variable designInvalid combinationsTypes, validation, object schemas
Excessive -targetPartial graph surprisesNormal full plan/apply; use target for exceptional recovery
Direct state editsCorruptionTerraform state/moved/import mechanisms
Casual state rmTerraform loses managementControlled state procedure
Blind AI-generated codeHallucination/security bugsMCP/docs + automated gates + review
Ignore costSurprise spendInfracost/FinOps review
Auto-apply PRs to prodUnreviewed changeMerge + protected approval
Long-lived CI credentialsHigh-value secretOIDC federation

PART 26 โ€” Security Best Practices

40. Security checklist

Identity
[ ] No hardcoded cloud credentials
[ ] CI uses OIDC/workload identity
[ ] Developer auth uses SSO/short-lived credentials
[ ] Plan and apply roles follow least privilege
[ ] Production permissions separated from non-production

State
[ ] State is remote
[ ] State is encrypted
[ ] State access is restricted
[ ] State locking enabled
[ ] State versioning/history enabled where supported
[ ] State access/audit is monitored
[ ] State never committed to Git

Code/dependencies
[ ] Terraform version constrained
[ ] Providers constrained
[ ] .terraform.lock.hcl committed for root configurations
[ ] Modules explicitly versioned
[ ] Dependency updates automated but reviewed
[ ] No secrets in tfvars/source

Review
[ ] Branch protection enabled
[ ] Required reviewers defined
[ ] Security scan required
[ ] Tests required
[ ] Plan required
[ ] Destruction/replacement explicitly reviewed
[ ] Production approval protected

Runtime
[ ] Policy-as-code for critical invariants where justified
[ ] Audit logs retained
[ ] Drift/health monitoring enabled
[ ] Break-glass process documented
Code language: PHP (php)

State is a security asset

Terraform state may contain:

  • database passwords,
  • generated tokens,
  • private endpoint metadata,
  • identifiers,
  • provider-returned secrets.

Marking an output sensitive = true primarily controls display; it does not magically remove the value from all state.

Prefer Terraform/provider features that avoid persistence when possible, including ephemeral values and write-only arguments where supported.


PART 27 โ€” Terraform Code Review Checklist

41. PR checklist

Intent

[ ] Ticket/goal is clear
[ ] Change is minimal for the intended outcome
[ ] Correct environment/account/region is targeted

Code quality

[ ] terraform fmt passes
[ ] terraform validate passes
[ ] TFLint passes
[ ] Naming is consistent
[ ] Variables are typed and validated
[ ] Inputs/outputs are documented
[ ] No unnecessary abstraction

Dependencies

[ ] Terraform constraint appropriate
[ ] Provider constraints appropriate
[ ] Lock-file changes expected
[ ] Reusable module versions pinned
[ ] Major dependency upgrades reviewed separately
Code language: CSS (css)

Security

[ ] No credentials/secrets
[ ] IAM is least privilege
[ ] No accidental 0.0.0.0/0 or ::/0
[ ] Encryption settings correct
[ ] Security scanner result reviewed
[ ] State/backend permissions unaffected or intentionally changed

Plan/blast radius

[ ] Adds/changes/destroys match intent
[ ] Every replacement (`-/+`) understood
[ ] Database/storage replacement scrutinized
[ ] IAM/KMS/networking changes scrutinized
[ ] for_each/count key changes understood
[ ] Moved/imported resource addresses correct
[ ] No unexpected state churn
Code language: JavaScript (javascript)

Reliability/cost

[ ] HA assumptions still valid
[ ] Capacity/quotas considered
[ ] Cost delta acceptable
[ ] Tests cover important behavior
[ ] Rollback/recovery approach understood

Documentation/operations

[ ] terraform-docs output current
[ ] README/runbook updated if behavior changed
[ ] Monitoring/alerts adjusted if needed
[ ] Post-deploy verification defined

PART 28 โ€” Terraform Productivity Best Practices

42. Reduce developer time without lowering safety

1. Standard repository template

Pre-create:

versions.tf
variables.tf
outputs.tf
tests/
.tflint.hcl
.terraform-docs.yml
.pre-commit-config.yaml
CI workflow
Renovate config
README markers

2. Reusable modules, but not “module everything”

Create a module when you have:

  • repeated stable pattern,
  • meaningful abstraction,
  • security defaults worth centralizing,
  • clear consumer interface.

Do not wrap one resource in a module merely to claim standardization.

3. Fast local path

Target:

fmt + validate + lint + focused security + mock tests

in a developer-friendly feedback loop.

Put slow live integration tests in CI/nightly pipelines.

4. Pre-approved module catalog

Make secure defaults easy:

Need private S3 bucket
  โ†“
approved module
  โ†“
3โ€“5 meaningful inputs
  โ†“
encryption/logging/policy defaults already included
Code language: JavaScript (javascript)

5. Central CI templates

Do not copy 100 slightly different Terraform workflows. Provide versioned reusable CI workflows/components.

6. Automated documentation

Generated docs prevent “variable exists in code but not README.”

7. Automated dependency updates

Small continuous upgrades are usually safer than a two-year provider jump.

8. Cost feedback in PRs

Shift cost discussion before apply.

9. Remote execution

A consistent execution environment eliminates “worked on my laptop” differences and improves auditability.

10. Use AI for mechanical work

AI is excellent at:

  • repetitive HCL,
  • tests,
  • docs,
  • refactors.

Humans remain accountable for:

  • intent,
  • architecture,
  • security,
  • blast radius,
  • production approval.

PART 29 โ€” Tool Overlap and Decision Guide

43. Overlap matrix

terraform validate vs TFLint

Use both. They answer different questions.

Trivy vs Checkov

Start with one. Add the second only for distinct policies/compliance.

Sentinel vs OPA

  • HCP-first, integrated governance: Sentinel is natural.
  • Cross-platform policy strategy: OPA is natural.
  • HCP Terraform can support OPA too.
  • Consider Terraform Policy as it matures if HCL-native policy is attractive.

tfenv vs tenv

For new Terraform-centric standardization, choose tenv unless existing tfenv investment outweighs migration benefit.

Terraform vs Terragrunt

Start with Terraform. Add Terragrunt to solve actual repetition/orchestration pain.

GitHub Actions vs Atlantis

  • CI ecosystem + custom workflows: GitHub Actions.
  • Terraform-specific PR command workflow: Atlantis.
  • You can combine them if responsibilities are unambiguous: CI validates, Atlantis owns plan/apply.

Atlantis vs HCP Terraform

HCP Terraform is a broader platform: state, runs, RBAC, registry, agents, policy, health. Atlantis is a focused PR automation server.

terraform test vs Terratest

Start native. Add Terratest for real behavioral integration.

terraform-docs vs manual README

Use both:

Manual sections โ†’ why/how/architecture
Generated section โ†’ exact interface reference
Code language: PHP (php)

pre-commit vs CI

Use both:

pre-commit = developer speed
CI         = enforcement

PART 30 โ€” Final Gold Standard Recommendation

44. Final stack

MUST HAVE

Terraform CLI
Git
terraform fmt
terraform validate
version constraints
.terraform.lock.hcl for root configs
remote state + locking for teams
code review
CI for production
OIDC/workload identity
plan review

STRONGLY RECOMMENDED

VS Code + HashiCorp Terraform Extension
terraform-ls
tenv
TFLint
Trivy
terraform test
terraform-docs
pre-commit-terraform
Infracost
Renovate
standard repository templates
reusable CI templates
post-deployment verification

OPTIONAL

Terraform MCP Server (recommended if AI is used)
Checkov
Terratest
Terragrunt
Atlantis
Conftest
tfupdate

ENTERPRISE / PLATFORM

HCP Terraform
Terraform Enterprise
private module/provider registry
private agents
RBAC
run tasks
policy sets
Sentinel / OPA / Terraform Policy
audit logging
drift detection / continuous validation
central cost/security governance
Code language: PHP (php)

Terraform Developer GOLD Standard Checklist Before Merge

SCOPE
[ ] I can explain exactly what this PR changes and why.
[ ] I changed only the intended state boundary/environment.

CODE
[ ] terraform fmt -check passes.
[ ] terraform validate passes.
[ ] TFLint passes.
[ ] No duplicate/copy-paste architecture was introduced unnecessarily.
[ ] Variables are typed, described, and validated where useful.
[ ] Outputs are intentional and documented.

VERSIONS
[ ] Terraform version policy is satisfied.
[ ] Provider constraints are explicit.
[ ] .terraform.lock.hcl changes are expected and reviewed.
[ ] Registry module versions are explicit.

SECURITY
[ ] No cloud credentials, passwords, API keys, tokens, or private keys are committed.
[ ] CI uses OIDC/workload identity.
[ ] Trivy/selected IaC security scan passes or exceptions are approved.
[ ] IAM follows least privilege.
[ ] Public ingress/egress is intentional.
[ ] Encryption is enabled where required.
[ ] State remains protected.

TESTING
[ ] terraform test passes.
[ ] Important module behavior is asserted.
[ ] Live integration testing is added when native tests cannot prove the requirement.

PLAN
[ ] A plan exists for the correct target.
[ ] I reviewed additions, changes, deletions, and replacements.
[ ] I understand every destructive/replacement action.
[ ] Resource-address changes are intentional.
[ ] No unexpected IAM/KMS/network/database changes exist.
[ ] Blast radius is acceptable.

COST
[ ] Cost delta has been reviewed when material.
[ ] New always-on/large resources are intentional.

DOCS
[ ] terraform-docs output is current.
[ ] Architecture/runbooks are updated if behavior changed.

DEPLOYMENT
[ ] Apply will run from the approved controlled environment.
[ ] Production approval requirements are met.
[ ] Rollback/recovery is understood.
[ ] Post-deployment verification is defined.

AFTER
[ ] Monitoring/alerts will detect regressions.
[ ] Drift/continuous validation is enabled where appropriate.
Code language: JavaScript (javascript)

Opinionated reference architecture

For most modern platform teams, the cleanest production model is:

Developer laptop
  โ”œโ”€ SSO / short-lived local cloud auth
  โ”œโ”€ VS Code + HashiCorp extension
  โ”œโ”€ tenv
  โ”œโ”€ fmt / validate / TFLint / Trivy / terraform test
  โ””โ”€ pre-commit
            โ†“
Protected Git repository
            โ†“
CI
  โ”œโ”€ reproduce local checks
  โ”œโ”€ dependency/supply-chain controls
  โ”œโ”€ OIDC
  โ”œโ”€ speculative/real plan
  โ””โ”€ cost/security feedback
            โ†“
HCP Terraform / TFE or dedicated controlled execution
  โ”œโ”€ remote state
  โ”œโ”€ locking
  โ”œโ”€ RBAC
  โ”œโ”€ private agents only when network access requires them
  โ”œโ”€ run tasks
  โ”œโ”€ policy
  โ””โ”€ approvals
            โ†“
Cloud
            โ†“
Verification + observability + drift/health
Code language: PHP (php)

This is intentionally boring. Boring infrastructure delivery is good: deterministic, reviewable, repeatable, auditable, and difficult to bypass accidentally.


Source and currency notes

This handbook was checked against current vendor/project documentation available on 5 September 2026, including:

  • HashiCorp Terraform CLI, testing, state, backend, policy, MCP Server, HCP Terraform, and Terraform Enterprise documentation.
  • HashiCorp Terraform VS Code extension andย terraform-ls.
  • tofuutilsย tenv.
  • terraform-linters TFLint and AWS ruleset.
  • Aqua Security Trivy.
  • Checkov.
  • terraform-docs.
  • Infracost.
  • antonbabenko/pre-commit-terraform.
  • Gruntwork Terragrunt and Terratest.
  • Atlantis.
  • Open Policy Agent and Conftest.
  • Renovate.
  • tfupdate.
  • GitHub Actions / AWS OIDC and GitLab OIDC documentation.

Selected official/reference URLs:

https://developer.hashicorp.com/terraform/
https://developer.hashicorp.com/terraform/mcp-server
https://developer.hashicorp.com/terraform/cloud-docs
https://developer.hashicorp.com/terraform/enterprise
https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform
https://github.com/hashicorp/terraform-ls
https://github.com/tofuutils/tenv
https://github.com/terraform-linters/tflint
https://trivy.dev/
https://www.checkov.io/
https://terraform-docs.io/
https://www.infracost.io/docs/
https://github.com/antonbabenko/pre-commit-terraform
https://terragrunt.gruntwork.io/
https://terratest.gruntwork.io/
https://www.runatlantis.io/
https://www.openpolicyagent.org/
https://www.conftest.dev/
https://docs.renovatebot.com/
https://github.com/minamijoyo/tfupdate
Code language: JavaScript (javascript)

Final operating principle

Terraform quality is not produced by Terraform alone.

A production Terraform system combines:

Correct code
+ reproducible versions
+ secure identities
+ protected state
+ automated lint/security/test gates
+ visible cost
+ reviewable plan
+ policy where it adds real value
+ controlled execution
+ post-deployment verification
Code language: PHP (php)

That combination turns Terraform from a command-line tool into an engineering platform.

Find Trusted Cardiac Hospitals

Compare heart hospitals by city and services โ€” all in one place.

Explore Hospitals
I'm Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms. I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.

Related Posts

Apple App Store Commission, In-App Purchases, External Payments, and How to Legally Design Apps for 0% Apple Commission

Current iOS/iPadOS payment-policy, architecture, and App Review reference Last verified September 5, 2026 Primary authority Apple Developer documentation + App Review Guidelines U.S. legal status Cross-checked against…

Read More

Top 10 AI Text-to-Video Generators With Audio in 2026

Updated: September 4, 2026 AI video generation has changed dramatically in 2026. We are no longer talking about tools that simply animate an image for five seconds….

Read More

Navigating Modern Technology: How Organizations Build, Scale, and Transform

Introduction Modern businesses increasingly depend on software, cloud infrastructure, artificial intelligence, automation, and reliable digital platforms to operate and compete. Yet, simply adopting individual technologies in isolation…

Read More

How to Choose the Right Website Development and SEO Partner for Your Business

A professional website has evolved far beyond a digital business card or an online brochure. Today, it serves as the core foundation of a brand’s entire online…

Read More

A Practical Guide to Training, Tools, Certifications and Modern Data Operations

Introduction Organizations today rely heavily on data to make critical decisions, power customer applications and build machine-learning models. However, as companies adopt cloud platforms, real-time streaming systems…

Read More

A Complete Guide to Exploring Amaravati: Events, Attractions and Things to Do

Amaravati stands out as a destination where history, spirituality, culture, the Krishna River, heritage attractions, and modern development come together. Both residents and visitors often look for…

Read More
Subscribe
Notify of
guest
0 Comments
Newest
Oldest Most Voted
0
Would love your thoughts, please comment.x
()
x