cloud IaC terraform ci claude-curated
Terraform without CI is a single developer with a laptop and admin credentials. CD for Terraform turns the workflow into something a team can use safely: every change is a PR, plans are visible, applies require approval, state is locked, and an audit trail exists. There are several products that solve this; the choice trades cost against control. The pattern is a flavour of GitOps applied to IaC.
The options
| Tool | Hosting | Cost | Notes |
|---|---|---|---|
| Terraform Cloud (TFC) | SaaS | Per-resource pricing | Bundles state, runs, policy, drift detection. See Terraform Cloud Workspaces |
| HCP Terraform | SaaS | Successor branding for TFC | Same product |
| Atlantis | Self-hosted | Free | PR-driven, single Go binary, simple to run |
| Spacelift | SaaS | Per-run pricing | Strong policy, multi-IaC (TF, Pulumi, CloudFormation) |
| env0 | SaaS | Per-user pricing | Cost estimation, drift detection |
| GitHub Actions | SaaS / hosted | Per-minute | Bring-your-own pipeline, full control |
| GitLab CI | SaaS / hosted | Per-minute | Similar to GHA, GitLab-integrated |
| Jenkins | Self-hosted | Free (you operate it) | Maximum flexibility, maximum operational burden |
Comparison dimensions
The right choice depends which of these you weight most.
- Cost. TFC and Spacelift charge per managed resource or per run; large estates can hit five-figure monthly bills. Atlantis and DIY GHA/GitLab are essentially free aside from compute.
- Drift detection. TFC, Spacelift, env0 ship this as a feature. With Atlantis or DIY you build it yourself (a scheduled job that runs
planper workspace). - Plan output in PR comments. All of the above can do this. The polish varies — TFC and Spacelift have rich UIs; Atlantis sticks the raw plan in a comment.
- Policy as code. TFC supports Sentinel and OPA; Spacelift supports OPA; Atlantis can shell out to
conftest. DIY pipelines need explicit OPA steps. - State locking. TFC and Spacelift handle this themselves. Atlantis and DIY rely on the configured backend (S3 + DynamoDB, GCS, etc.) to provide locking.
- Audit trail. SaaS products give you a UI of “who did what when”. DIY gives you whatever the underlying CI logs already provide — see CloudTrail Auditing for AWS-side equivalent.
Terraform Cloud
The lowest-effort option for teams that don’t want to operate any infra to manage their infra.
- Connect a workspace to a Git repo; TFC speculates on PRs and applies on merge.
- Variables and secrets are stored in TFC, not in the repo.
- Sentinel or OPA policies gate runs.
- The catch is cost — pricing scales with managed resources, and at the upper end (thousands of resources, multiple environments) the bill becomes a procurement decision rather than an engineering one. See Terraform Cloud Pitfalls.
Best for small-to-medium estates where the team’s time is more expensive than per-resource pricing.
Atlantis
A PR-driven, self-hosted Terraform runner. Deploy as a single Go binary or container; it listens for webhooks from GitHub/GitLab/Bitbucket and posts plans into PR comments.
Workflow:
- Open a PR. Atlantis automatically runs
planand comments the output. - Reviewer reads the plan, comments
atlantis applyoratlantis apply -p <project>. - Atlantis applies, posts the result.
- Merge.
Pros: free, you own the data, simple operational model. Cons: you operate it (a small VM and a webhook is enough but not zero), no drift detection out of the box, less polished UI.
A common pattern is Atlantis + S3/DynamoDB backend + OPA via conftest. The whole stack is open source, runs on a single small VM, and handles a surprising amount of scale.
GitHub Actions (or GitLab CI)
Maximum flexibility, maximum responsibility. You write your own pipeline.
A typical layout:
on:
pull_request:
push:
branches: [main]
jobs:
plan:
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform plan -out=tfplan
- uses: actions/upload-artifact@v4
with: { name: tfplan, path: tfplan }
# post plan output as a PR comment
apply:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment: production # gates with reviewers
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform apply -auto-approveYou handle:
- Posting plan output to the PR (a community action like
actions/github-scriptor a dedicated TF action). - Preserving the plan file between plan and apply (artifact upload, or run apply on the merged commit’s plan).
- Manual approval gates (GitHub
environmentswith required reviewers). - Secrets management (GitHub OIDC into AWS, environment secrets) — consider Vault or Secrets Manager.
- Drift detection (a scheduled workflow that runs
planand alerts on non-empty diff). See Terraform State Drift.
The advantage is you’re not paying per-resource and you can shape the pipeline however you want. The disadvantage is everything that TFC or Spacelift gives you out of the box, you build.
Common patterns regardless of tool
- PR-driven plans. Every change opens a PR; CI posts the plan; review happens against the diff.
- Manual approval for prod. Lower environments auto-apply; production requires a second human’s approval click.
- One workspace per environment. Don’t try to use Terraform CLI workspaces (
terraform workspace) to manage prod and dev in one config. Separate root modules with separate state files. Keeps blast radius small and policies easier. See Terraform Module Composition. - Pinned Terraform version.
required_versionin config plus a CI step that asserts the version. Avoids “works on my laptop” plan drift. - Provider lockfile in the repo.
.terraform.lock.hclis committed so CI and laptops resolve identical provider versions. - No long-lived cloud credentials in CI. OIDC into AWS / GCP / Azure to mint short-lived creds per run. Apply Least Privilages on the assumed IAM role.
- Plan-then-apply, not plan-and-apply. The PR shows the plan; merge applies the same plan. Don’t re-plan on apply or you risk applying something different to what was reviewed.
Choosing
A reasonable decision tree:
- Brand-new team, small estate, prefers managed: Terraform Cloud.
- Existing team, cost-sensitive, willing to run a VM: Atlantis.
- Already deeply invested in GitHub or GitLab and want to write the pipeline yourself: GitHub Actions / GitLab CI.
- Multi-IaC estate (Terraform + Pulumi + CFN), policy-heavy: Spacelift.
- Cost estimation and self-service environments matter most: env0.
The most common path I’ve seen: start with GitHub Actions because it’s already there, outgrow it as the policy and drift-detection load grows, then move to TFC or Atlantis. Migrating later is annoying but not catastrophic. Pair with Terraform CLI with Cloud Hybrid for surgical operations the pipeline can’t do.
See also
- Terraform Cloud Workspaces
- Terraform CLI with Cloud Hybrid
- Terraform Cloud Pitfalls
- Terraform Module Composition
- Terragrunt