This post explains the CloudFormation template that sets up the backend (S3/DynamoDB) to store Terraform state.
Introduction
How to provision the backend for storing Terraform state can be a point of consideration.
Implementing it with Terraform itself can be a bit of a hassle (the problem of “how do you manage the state of that Terraform?”), so it’s often better to use something other than Terraform.
On AWS, CloudFormation is one such alternative.
Here’s a CloudFormation template to provision a Terraform backend.
Note: This article was translated from my original post.
CloudFormation Template to Provision Terraform Backend
Here’s a sample implementation.
(The code on GitHub is here)
AWSTemplateFormatVersion: '2010-09-09' Description: 'Create S3 and DynamoDB resources for Terraform backend' Parameters: ResourceNamePrefix: Type: String Description: 'The prefix for the resource names (S3 bucket and DynamoDB table)' Default: 'demo' Resources: TerraformStateBucket: Type: 'AWS::S3::Bucket' Properties: BucketName: !Sub '${ResourceNamePrefix}-${AWS::AccountId}-terraform-state' VersioningConfiguration: Status: 'Enabled' LifecycleConfiguration: Rules: - Id: ExpireNoncurrentVersions NoncurrentVersionExpirationInDays: 90 Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: 'AES256' AccessControl: 'Private' PublicAccessBlockConfiguration: BlockPublicAcls: true IgnorePublicAcls: true BlockPublicPolicy: true RestrictPublicBuckets: true DynamoDBLockTable: Type: 'AWS::DynamoDB::Table' Properties: TableName: !Sub '${ResourceNamePrefix}-terraform-lock' AttributeDefinitions: - AttributeName: 'LockID' AttributeType: 'S' KeySchema: - AttributeName: 'LockID' KeyType: 'HASH' BillingMode: 'PAY_PER_REQUEST' Outputs: TerraformStateBucketName: Description: 'The name of the S3 bucket for storing Terraform state files' Value: !Ref TerraformStateBucket DynamoDBLockTableName: Description: 'The name of the DynamoDB table for Terraform state locking' Value: !Ref DynamoDBLockTable
S3:
- Default encryption (SSE-S3)
- Versioning enabled
- Block public access enabled
DynamoDB:
- Required schema setup
- PAY_PER_REQUEST billing mode
This can be used as a starting point, and extended to match your specific needs.
Examples:
- Encrypting S3 with CMK
- Bucket policies for access control / cross-account permissions
- etc...
Conclusion
I’ve shared a sample implementation of a CloudFormation template to provision a Terraform backend.
If you use something like Terraform Cloud, this kind of setup might be handled automatically. However, personally, I’ve only used Terraform in its open-source version, so I still need to manually prepare the backend in this manner.
Hope this helps someone out there.
[Related Article]
References
- GitHub - thoughtbot/cloudformation-terraform-state-backend: Cloudformation template to create Terraform state S3 backend
- GitHub - tiborhercz/tf-state-backend-s3-cloudformation: CloudFormation template to provision a state backend for Terraform
- GitHub - bioerrorlog/terraform-examples: My terraform example projects.