Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 9 min read

Running Terraform Safely in CI/CD Pipelines

Letting CI run terraform apply unattended is powerful and terrifying. Here's the pipeline structure, gates, and credential handling I use to do it without blowing up prod.

  • #terraform
  • #ci-cd
  • #automation
  • #pipelines
  • #devops
  • #gitops

Running Terraform from a laptop doesn’t scale and doesn’t audit. Eventually every serious estate moves apply into CI/CD. The trouble is that an unattended terraform apply with production credentials is one bad merge away from a very bad day. After 25 years I’ve settled on a pipeline structure that gets the automation benefits without handing the robot a loaded weapon.

Here’s how I wire it up.

Separate plan from apply, always

The single most important rule: plan and apply are different stages with different triggers.

  • plan runs on every pull request. It’s read-only and safe. Its job is to show reviewers exactly what will change.
  • apply runs only after merge to the protected branch, and only against a saved plan from that exact commit.
plan:
  on: pull_request
  run: terraform plan -out=tfplan

apply:
  on:
    push:
      branches: [main]
  run: terraform apply tfplan

Applying a saved plan file is critical. It guarantees CI applies exactly what was reviewed — not a fresh plan computed against whatever the world looks like at merge time.

Post the plan where humans see it

A plan buried in CI logs gets rubber-stamped. Render it into the PR as a comment so the diff is the first thing a reviewer sees:

Plan: 2 to add, 1 to change, 0 to destroy.

That “0 to destroy” line is the one I scan for every single time. A reviewer who sees the human-readable plan inline catches the dangerous changes that get lost in a wall of logs.

Credentials: short-lived, never stored

Long-lived cloud keys in CI secrets are a breach waiting to happen. Use OIDC federation so the pipeline assumes a role and gets short-lived credentials per run:

permissions:
  id-token: write
- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789:role/tf-ci-apply
    aws-region: us-east-1

No static keys to leak. The plan role is read-only; the apply role can write but is scoped to exactly what the estate needs. Least privilege isn’t optional for a robot with production access.

Gates that prevent disasters

A few gates I put between merge and a production apply:

  • Manual approval on production environments. CI computes and presents the plan; a human clicks go.
  • Policy-as-code via OPA/Conftest or Sentinel that fails the build on, say, a public S3 bucket or an untagged resource.
  • Destroy guards — a job that fails automatically if the plan deletes a resource tagged protect=true.
  • Concurrency locks so two pipelines never apply the same state at once. The backend lock helps, but failing fast in CI is cleaner than a mid-apply collision.

Pin everything for reproducibility

A pipeline that floats its Terraform and provider versions is non-deterministic. Pin the Terraform binary, commit your .terraform.lock.hcl, and pin module sources to tags. The plan a reviewer approved must be the plan that applies — version drift between stages quietly breaks that promise.

Where AI fits in the pipeline

I use AI in two places around the pipeline, never inside the apply itself.

First, on the PR: an assistant summarizes the rendered plan in plain English — “this adds two subnets and widens an SG ingress to 0.0.0.0/0, which you probably didn’t intend.” That extra read catches the change a tired reviewer skims past. Our Code Review tool does this as a structured pass on the diff.

Second, for pipeline authoring itself, I keep Terraform prompts for generating the OIDC config, policy rules, and destroy-guard jobs. AI is great at the YAML boilerplate.

What AI never does: approve a plan or trigger an apply. The gate stays human.

The takeaway

Safe Terraform CI/CD comes down to a few hard lines: split plan from apply, apply only saved plans, use short-lived OIDC credentials with least privilege, render plans into the PR, and gate production behind human approval and policy. Get those right and CI becomes the safest place to run Terraform — more auditable and more consistent than any laptop ever was.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.