Generate Terraform Backend
The backend section generates Terraform backend configuration files (backend.tf.json)
for your components. Define backend settings once in your stacks and Atmos generates
the appropriate files for each environment.
How It Works
When you run any atmos terraform command, Atmos:
- Reads your
backendandbackend_typeconfiguration from the stack - Deep-merges settings from all inherited stack manifests
- Generates a
backend.tf.jsonfile in the component directory - Terraform uses this file to configure state storage
This separation means your Terraform modules stay clean—no hardcoded backend configuration in your source code.
Add backend.tf.json to your .gitignore since these files are generated automatically by Atmos and should not be committed to version control:
# Atmos generated files
backend.tf.json
Some automation systems may require the generated file to be committed—in those cases,
committing backend.tf.json is acceptable.
Use Cases
- State Management: Configure S3, Azure Blob, GCS, or other backends for remote state storage.
- Environment Isolation: Use different state storage per environment or account.
- State Locking: Configure native locking (
use_lockfile) or DynamoDB for legacy setups. - Remote State Access: Configure
remote_state_backendfor cross-component state references.
Configuration Scopes
Backend settings can be defined at multiple levels, with more specific scopes overriding broader ones:
| Scope | Example File | Effect |
|---|---|---|
| Organization | stacks/orgs/acme/_defaults.yaml | All components inherit |
| Account/Stage | stacks/orgs/acme/plat/prod/_defaults.yaml | Override for prod |
| Component-type | Under terraform: in any stack | All Terraform components |
| Component | Under components.terraform.<name>: | Single component |
Component-Type Level
Backend settings defined under terraform apply to all Terraform components:
- Stack Configuration
- Generated File
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
encrypt: true
use_lockfile: true
{
"terraform": {
"backend": {
"s3": {
"bucket": "acme-ue1-root-tfstate",
"region": "us-east-1",
"encrypt": true,
"use_lockfile": true,
"key": "ue1/prod/vpc/terraform.tfstate"
}
}
}
}
Component Level
Backend settings within a component override the defaults:
- Stack Configuration
- Generated File
components:
terraform:
special-component:
backend_type: s3
backend:
s3:
bucket: acme-ue1-prod-special-tfstate
key: "special/terraform.tfstate"
{
"terraform": {
"backend": {
"s3": {
"bucket": "acme-ue1-prod-special-tfstate",
"key": "special/terraform.tfstate"
}
}
}
}
Backend Types
Atmos supports all Terraform backend types. Configure using backend_type and the corresponding configuration under backend.
S3 Backend
The most common backend for AWS environments. We recommend using use_lockfile: true for native S3 state locking (Terraform 1.10+, OpenTofu 1.8+) instead of DynamoDB:
- Stack Configuration
- Generated File
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
key: "{{ .environment }}/{{ .stage }}/{{ .component }}/terraform.tfstate"
encrypt: true
use_lockfile: true # Native S3 locking (Terraform 1.10+)
{
"terraform": {
"backend": {
"s3": {
"bucket": "acme-ue1-root-tfstate",
"region": "us-east-1",
"key": "ue1/prod/vpc/terraform.tfstate",
"encrypt": true,
"use_lockfile": true
}
}
}
}
S3 Backend with Assume Role
For cross-account access, configure the backend to assume a role:
- Stack Configuration
- Generated File
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
key: "{{ .environment }}/{{ .stage }}/{{ .component }}/terraform.tfstate"
encrypt: true
use_lockfile: true
assume_role:
role_arn: "arn:aws:iam::{{ .vars.state_account_id }}:role/TerraformStateAccess"
session_name: "atmos-{{ .component }}"
{
"terraform": {
"backend": {
"s3": {
"bucket": "acme-ue1-root-tfstate",
"region": "us-east-1",
"key": "ue1/prod/vpc/terraform.tfstate",
"encrypt": true,
"use_lockfile": true,
"assume_role": {
"role_arn": "arn:aws:iam::123456789012:role/TerraformStateAccess",
"session_name": "atmos-vpc"
}
}
}
}
}
S3 Backend with SSE-C Encryption
For state files encrypted with SSE-C (Server-Side Encryption with Customer-Provided Keys),
provide the customer key so that !terraform.state can decrypt state when reading directly from S3:
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
key: "{{ .environment }}/{{ .stage }}/{{ .component }}/terraform.tfstate"
encrypt: true
use_lockfile: true
sse_customer_key: "base64-encoded-32-byte-key"
The sse_customer_key must be a base64-encoded 256-bit (32-byte) key. It can also be provided via the AWS_SSE_CUSTOMER_KEY
environment variable. The backend attribute takes precedence over the environment variable.
The sse_customer_key attribute is used by Atmos when reading state directly via !terraform.state.
Terraform/OpenTofu handles SSE-C independently through its own backend configuration.
S3 Backend with DynamoDB Locking (Legacy)
For Terraform versions before 1.10, use DynamoDB for state locking:
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
key: "{{ .environment }}/{{ .stage }}/{{ .component }}/terraform.tfstate"
dynamodb_table: acme-ue1-root-tfstate-lock
encrypt: true
Azure Blob Backend
For Azure environments:
- Stack Configuration
- Generated File
terraform:
backend_type: azurerm
backend:
azurerm:
resource_group_name: terraform-state-rg
storage_account_name: tfstateaccount
container_name: tfstate
key: "{{ .environment }}/{{ .stage }}/{{ .component }}/terraform.tfstate"
{
"terraform": {
"backend": {
"azurerm": {
"resource_group_name": "terraform-state-rg",
"storage_account_name": "tfstateaccount",
"container_name": "tfstate",
"key": "ue1/prod/vpc/terraform.tfstate"
}
}
}
}