atmos ai skill install atmos-terraformAtmos Terraform and OpenTofu Orchestration
Atmos wraps the Terraform or OpenTofu CLI to provide stack-aware orchestration of infrastructure operations. Instead of manually managing workspaces, backends, variable files, and authentication for each component, Atmos resolves the full configuration from stack manifests and handles all of these concerns automatically.
Everything in this skill applies identically to Terraform and OpenTofu. The atmos terraform command
namespace is the same regardless of which binary is configured -- atmos terraform plan runs tofu plan when
the binary is set to tofu. Use the user's terminology in responses (if they say "OpenTofu," say "OpenTofu").
Terraform or OpenTofu: Binary Selection
Atmos defaults to the terraform binary. Switch to OpenTofu by setting components.terraform.command: tofu
in atmos.yaml. The setting cascades through CLI > env > config > defaults precedence and can be overridden
at multiple levels for mixed setups.
Global (whole project on OpenTofu)
# atmos.yamlcomponents:terraform:command: tofu # All atmos terraform commands invoke `tofu` instead of `terraform`base_path: components/terraform
Or via environment variable:
export ATMOS_COMPONENTS_TERRAFORM_COMMAND=tofuatmos terraform plan vpc -s dev # Runs: tofu plan
Per-stack override
Use terraform.overrides.command in a stack manifest to switch the binary for everything in that stack:
# stacks/orgs/acme/plat/prod/_defaults.yamlterraform:overrides:command: tofu
Per-component override
Set command on an individual component to run a single component on a different binary than the rest of
the stack (useful for legacy components that haven't been validated on OpenTofu, or new components testing
OpenTofu-specific features):
components:terraform:legacy-vpc:command: terraform # This component stays on Terraformvars: ...new-eks:command: tofu # This component runs on OpenTofuvars: ...
Per-invocation override
Pass --terraform-command on the CLI to override for a single command:
atmos terraform plan vpc -s dev --terraform-command=tofu
Installing and Pinning the Binary via Toolchain
The Atmos toolchain installs and pins both Terraform and OpenTofu so the same binary version runs
on every developer machine and in CI. Binary selection (command: terraform vs command: tofu)
and binary version pinning (dependencies.tools.terraform vs dependencies.tools.opentofu) are
independent settings -- command says which binary Atmos invokes, dependencies.tools.<name> says
which version the toolchain installs. Always pin both together; setting command: tofu without a
matching opentofu dependency leaves you at the mercy of whatever tofu is on PATH.
Pinning can be applied at four scopes, in increasing precedence:
- Project-wide --
.tool-versions(asdf-compatible) at the repo root for defaults everyone shares. - Stack-wide --
dependencies.toolsin a stack default to pin a whole stack scope. - Component-type --
terraform.dependencies.toolsto default every Terraform/OpenTofu component. - Per-component --
dependencies.toolson an individual component for migrations or one-offs.
Atmos installs declared tools when running the component. Use atmos toolchain install only to
pre-warm a cache, bootstrap a shell, or troubleshoot a specific binary. For full YAML examples,
resolution order, ad-hoc installs, and the inspection workflow, see
references/toolchain-pinning.md and the
atmos-toolchain skill.
OpenTofu-specific considerations
- State encryption (OpenTofu 1.7+) -- a Terraform-incompatible feature; if enabled, state can no longer
be read by
terraform. Switching back is not zero-effort. removedblocks -- supported by both binaries in recent versions; no Atmos-side difference.- Provider/module registry -- OpenTofu uses
registry.opentofu.orgby default; pinned modules sourced fromregistry.terraform.iostill work in OpenTofu but consult the relevant registry availability when the user reports a missing module. terraform.required_version-- OpenTofu respects this constraint; pin appropriately.terraform { backend ... }block -- identical syntax in both binaries; no Atmos-side change needed.
For users running mixed Terraform/OpenTofu deployments, the per-component or per-stack override pattern is the right tool. Do not propose a project-wide switch unless the user has validated all components against OpenTofu.
How Atmos Orchestrates Terraform
When you run any atmos terraform command, Atmos performs the following sequence:
- Resolves stack configuration -- Reads and deep-merges all stack manifests to produce the fully resolved configuration for the target component in the target stack.
- Generates backend configuration -- Writes a
backend.tf.jsonfile in the component directory with the correct backend settings (S3 bucket, key, region, etc.) derived from the stack config. - Generates variable file -- Writes a
terraform.tfvars.jsonfile containing allvarsdefined for the component in the stack. - Provisions backend infrastructure -- If
provision.backend.enabled: true, creates the backend storage (e.g., S3 bucket) before Terraform init. - Runs
terraform init-- Initializes the working directory with the generated backend config. Cleans.terraform/environmentfirst and optionally adds-reconfigure. - Selects or creates workspace -- Calculates the Terraform workspace name from context variables and selects it (or creates it if it does not exist).
- Executes the requested command -- Runs
terraform plan,apply,destroy, etc. with the generated varfile and any additional flags.
This means a single command like atmos terraform plan vpc -s plat-ue2-dev replaces what would normally
require multiple manual steps: configuring the backend, writing tfvars, running init, selecting the workspace,
and then running plan.
Core Commands
plan
Generates a Terraform execution plan showing what changes would be made.
atmos terraform plan <component> -s <stack>
By default, Atmos saves the plan to a file using the naming convention <context>-<component>.planfile.
This planfile can later be used with --from-plan to apply the exact reviewed changes.
# Basic planatmos terraform plan vpc -s plat-ue2-dev# Skip planfile generation (useful for Terraform Cloud)atmos terraform plan vpc -s dev --skip-planfile# Plan with custom output pathatmos terraform plan vpc -s dev -out=/tmp/my-plan.tfplan# Plan only specific resourcesatmos terraform plan vpc -s dev -target=aws_subnet.private
apply
Applies Terraform changes. Supports interactive approval, planfile-based apply, and auto-approve.
atmos terraform apply <component> -s <stack>
# Interactive apply (prompts for confirmation)atmos terraform apply vpc -s plat-ue2-dev# Apply from a previously generated planatmos terraform plan vpc -s devatmos terraform apply vpc -s dev --from-plan# Apply a specific planfileatmos terraform apply vpc -s dev --planfile /tmp/my-plan.tfplan# Auto-approved apply (no confirmation prompt)atmos terraform apply vpc -s dev -auto-approve
deploy
Combines plan and apply with automatic approval. This is the most common command for CI/CD pipelines.
atmos terraform deploy <component> -s <stack>
Key differences from apply:
- Automatically sets
-auto-approve-- no interactive confirmation - Supports
--deploy-run-initto control whether init runs - Designed for automated, non-interactive deployments
# Deploy a componentatmos terraform deploy vpc -s plat-ue2-dev# Deploy from a previously generated planatmos terraform deploy vpc -s dev --from-plan# Deploy a specific planfileatmos terraform deploy vpc -s dev --planfile /tmp/vpc-plan.tfplan
destroy
Destroys all resources managed by a component in a stack. Accepts -auto-approve and -target=...
just like upstream Terraform: atmos terraform destroy vpc -s dev.
init
Atmos runs terraform init automatically before plan, apply, and deploy, so manual invocation is
rarely needed. When required, all upstream init flags pass through (-reconfigure, -upgrade,
-migrate-state): atmos terraform init vpc -s dev -reconfigure.
Multi-Component Operations
Atmos supports executing Terraform commands across multiple components simultaneously using filter flags.
These work with plan, apply, and deploy.
# All components in all stacksatmos terraform plan --all# All components in a specific stackatmos terraform plan --stack prod# Specific components across stacksatmos terraform deploy --components vpc,eks# Only components affected by git changes (in dependency order)atmos terraform deploy --affected# Affected with dependents includedatmos terraform deploy --affected --include-dependents# Filter by YQ query expressionatmos terraform plan --query '.vars.tags.team == "eks"'# Combine filtersatmos terraform plan --affected --stack prod# Always preview first with --dry-runatmos terraform deploy --all --dry-run
Workspace Management
Atmos computes the Terraform workspace name from stack context (namespace, tenant, environment,
stage, component), runs terraform init -reconfigure, and selects (or creates) the workspace
on every invocation. Explicit management is also available: atmos terraform workspace vpc -s plat-ue2-dev.
For stable workspace keys across component implementations, use metadata.name on an abstract
base component (name: vpc, component: vpc/v2); for dynamic naming, workspace_key_prefix
under backend: accepts Go templates. Toggle the runtime behavior via
components.terraform.init_run_reconfigure and workspaces_enabled in atmos.yaml. Full
examples are in references/backend-configuration.md.
Backend Configuration and Auto-Generation
With components.terraform.auto_generate_backend_file: true in atmos.yaml, Atmos reads
backend_type and backend from the resolved stack config, deep-merges through the stack
hierarchy (org → tenant → environment → stage → component), and writes backend.tf.json into
the component directory before terraform init. Add backend.tf.json to .gitignore.
Regenerate manually with atmos terraform generate backend vpc -s plat-ue2-dev. For full
examples covering S3, GCS, Azure, and remote backends, plus workspace key prefix patterns, see
references/backend-configuration.md.
Variable File Generation
Atmos generates terraform.tfvars.json from the vars section in the stack configuration. This happens
automatically before plan/apply/deploy, but can also be invoked manually:
atmos terraform generate varfile vpc -s plat-ue2-dev# Output to a custom fileatmos terraform generate varfile vpc -s plat-ue2-dev -f vars.json
Planfile Generation
Generate planfiles in JSON or YAML format for review or integration with tools like Checkov:
atmos terraform generate planfile vpc -s plat-ue2-devatmos terraform generate planfile vpc -s dev --format=jsonatmos terraform generate planfile vpc -s dev --format=yaml --file=planfile.yaml
Authentication Configuration
Terraform commands can use Atmos auth identities from atmos.yaml or component-level auth.identity.
Keep detailed provider/profile setup in atmos-auth; this skill should only recommend the Terraform
runtime controls:
atmos terraform plan vpc -s prod --identity prod-adminatmos terraform plan vpc -s dev --identity ""
Backend Provisioning
Backend configuration and backend provisioning are different:
backend_typeandbackendtell Terraform where state lives and generatebackend.tf.json.provision.backend.enabled: truetells Atmos to create the backend storage before first use.
Set provision.backend.enabled: true in stack config to auto-provision backend infrastructure,
solving the Terraform bootstrap problem. Manual provisioning is available via
atmos terraform backend create/list/describe/update/delete. Backend provisioning currently applies
to Terraform components. See
references/backend-configuration.md for details.
Source Provisioning and Workdirs
Use source for just-in-time component provisioning and pair it with provision.workdir for isolated
per-instance execution. Workdirs prevent shared .terraform, lockfile, backend, and varfile collisions
when the same component source is used by multiple stacks or runs.
components:terraform:vpc:source:uri: github.com/cloudposse-terraform-components/aws-vpc.gitversion: 1.450.0provision:workdir:enabled: true
With workdirs enabled, Atmos stages the provisioned source into the instance workdir and runs Terraform there. Without workdirs, source provisioning targets the component path.
Interactive Shell
The shell command drops you into a shell pre-configured with all the context for a component in a stack.
Varfiles, backend config, and workspace are all set up so you can run native Terraform commands directly.
atmos terraform shell vpc -s plat-ue2-dev
Inside the shell:
- The working directory is the component's folder
terraform.tfvars.jsonandbackend.tf.jsonare generated- The correct workspace is selected
- All required ENV vars are set
ATMOS_SHLVLtracks shell nesting level
Customize the shell prompt in atmos.yaml:
components:terraform:shell:prompt: "atmos [{{.Stack}}] {{.Component}} $ "
Additional Commands
Atmos supports output, validate, state, clean, console, fmt, get, import, show,
taint/untaint, force-unlock, refresh, graph, and providers -- all standard Terraform
subcommands with the same atmos terraform <cmd> <component> -s <stack> syntax. For the complete
reference, see references/commands-reference.md.
# Common examplesatmos terraform output vpc -s dev vpc_idatmos terraform state list vpc -s devatmos terraform clean vpc -s dev
Common Flags
| Flag | Short | Description |
|---|---|---|
--stack | -s | Target Atmos stack (required for single-component) |
--dry-run | Preview without executing | |
--skip-init | Skip automatic terraform init | |
--from-plan | Apply a previously generated planfile | |
--all | Target all components | |
--affected | Target git-affected components | |
--identity | Override authentication identity |
Use -- to pass flags directly to Terraform: atmos terraform plan vpc -s dev -- -refresh=false.
For the complete flag reference, see references/commands-reference.md.
Path-Based Component Resolution
You can use filesystem paths instead of component names:
cd components/terraform/vpcatmos terraform plan . -s devatmos terraform apply . -s dev
Supported path formats: ., ./component, ../sibling, /absolute/path.
If a path matches multiple components, Atmos prompts for selection in interactive mode.
Debugging
atmos describe component vpc -s plat-ue2-dev-- show the fully resolved configuration (merged vars, backend, workspace name, metadata, settings).atmos terraform plan vpc -s dev --dry-run-- preview what Atmos will do without executing.TF_LOG=DEBUG atmos terraform plan vpc -s dev-- enable upstream Terraform debug logging.
Configuration in atmos.yaml
Key settings under components.terraform include auto_generate_backend_file, init_run_reconfigure,
workspaces_enabled, deploy_run_init, apply_auto_approve, and plan.skip_planfile. Each has a
corresponding ATMOS_COMPONENTS_TERRAFORM_* environment variable override. See
references/backend-configuration.md for complete configuration details.
Best Practices
-
Use the two-stage plan/apply workflow for production. Run
planfirst, review the output, thenapply --from-planto ensure exactly the reviewed changes are applied. -
Use
deployfor automated pipelines. It combines plan and apply with auto-approve, ideal for CI/CD. -
Always preview multi-component operations with
--dry-runbefore executing--allor--affected. -
Let Atmos manage backend configuration. Set
auto_generate_backend_file: trueand define backend settings in stack manifests rather than hardcoding in Terraform modules. -
Use
atmos describe componentto debug configuration resolution issues. It shows the fully merged result of all stack manifest inheritance. -
Add generated files to .gitignore. The
backend.tf.jsonandterraform.tfvars.jsonfiles are generated at runtime and should not be committed. -
Use
atmos terraform shellfor interactive debugging. It sets up the full context so you can run native terraform commands directly. -
Enable backend provisioning (
provision.backend.enabled: true) to solve the Terraform bootstrap problem and ensure backends exist before first use. -
Use source provisioning with workdirs when components are pulled via
source, especially in CI or any multi-stack workflow that can run concurrently.
Additional Resources
- For the complete list of all
atmos terraformsubcommands, see references/commands-reference.md - For backend configuration patterns (S3, GCS, Azure, remote), see references/backend-configuration.md
- For toolchain-based Terraform/OpenTofu version pinning at each scope, see references/toolchain-pinning.md