_backend-config
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 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"
}
}
}
}
GCS Backend
For Google Cloud environments:
- Stack Configuration
- Generated File
terraform:
backend_type: gcs
backend:
gcs:
bucket: acme-terraform-state
prefix: "{{ .environment }}/{{ .stage }}/{{ .component }}"
{
"terraform": {
"backend": {
"gcs": {
"bucket": "acme-terraform-state",
"prefix": "ue1/prod/vpc"
}
}
}
}
Terraform Cloud / Enterprise
For Terraform Cloud or Enterprise:
- Stack Configuration
- Generated File
terraform:
backend_type: remote
backend:
remote:
hostname: app.terraform.io
organization: acme
workspaces:
name: "{{ .namespace }}-{{ .environment }}-{{ .stage }}-{{ .component }}"
Or using the newer cloud backend:
terraform:
backend_type: cloud
backend:
cloud:
organization: acme
workspaces:
name: "{{ .namespace }}-{{ .environment }}-{{ .stage }}-{{ .component }}"
{
"terraform": {
"backend": {
"remote": {
"hostname": "app.terraform.io",
"organization": "acme",
"workspaces": {
"name": "acme-ue1-prod-vpc"
}
}
}
}
}
Local Backend
For development or single-user scenarios:
- Stack Configuration
- Generated File
terraform:
backend_type: local
backend:
local:
path: "{{ .component }}/terraform.tfstate"
{
"terraform": {
"backend": {
"local": {
"path": "vpc/terraform.tfstate"
}
}
}
}
Remote State Backend
The remote_state_backend configuration is separate from backend and controls how other components can read this component's state:
terraform:
# Where this component stores its state
backend_type: s3
backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
# How other components read this component's state
remote_state_backend_type: s3
remote_state_backend:
s3:
bucket: acme-ue1-root-tfstate
region: us-east-1
This separation allows for scenarios like:
- Using Terraform Cloud for operations but S3 for remote state access
- Different credentials for writing vs. reading state
- Custom remote state configurations
Backend Provisioning
Atmos can automatically provision S3 backend infrastructure before running Terraform commands, solving the bootstrap problem of "how do I create state storage before I can use Terraform?"
Enable Automatic Provisioning
terraform:
backend_type: s3
backend:
s3:
bucket: acme-ue1-dev-tfstate
region: us-east-1
use_lockfile: true
provision:
backend:
enabled: true # Automatically create backend if it doesn't exist
When provision.backend.enabled is true, Atmos will:
- Check if the backend exists before running Terraform
- Create it with secure defaults (versioning, encryption, public access blocked)
- Proceed with normal Terraform operations
See Backend Provisioning for complete documentation.
Examples
Environment-Specific State Buckets
stacks/orgs/acme/plat/dev/_defaults.yaml
stacks/orgs/acme/plat/prod/_defaults.yaml
Dynamic State Keys with Templates
stacks/orgs/acme/_defaults.yaml
Component-Specific Backend Override
stacks/orgs/acme/plat/prod/us-east-1.yaml
Multi-Cloud Configuration
stacks/orgs/acme/aws/_defaults.yaml
stacks/orgs/acme/azure/_defaults.yaml
Workspace Configuration
For backends that support workspaces, you can configure workspace patterns:
terraform:
backend_type: remote
backend:
remote:
organization: acme
workspaces:
prefix: "acme-"
components:
terraform:
vpc:
terraform_workspace: "{{ .environment }}-{{ .stage }}-vpc"
See Terraform Workspaces for detailed workspace configuration.
Best Practices
-
Use Remote State: Always use a remote backend for team environments to enable collaboration and state locking.
-
Enable Encryption: Always enable encryption for backends that support it (S3, Azure Blob, GCS).
-
Configure State Locking: Use
use_lockfile: truefor S3 (Terraform 1.10+), blob leases for Azure, or built-in locking for other backends. -
Organize State Keys: Use a consistent key structure that includes environment, stage, and component information.
-
Separate Sensitive State: Consider using separate state buckets or additional encryption for components managing secrets.
-
Use Templates: Leverage Go templates for dynamic backend configuration based on context variables.