Module: tfstate-backend
Terraform module to provision an S3 bucket to store terraform.tfstate
file and a DynamoDB table to lock the state file
to prevent concurrent modifications and state corruption.
The module supports the following:
- Forced server-side encryption at rest for the S3 bucket
- S3 bucket versioning to allow for Terraform state recovery in the case of accidental deletions and human errors
- State locking and consistency checking via DynamoDB table to prevent concurrent operations
- DynamoDB server-side encryption
https://www.terraform.io/docs/backends/types/s3.html
NOTE: The operators of the module (IAM Users) must have permissions to create S3 buckets and DynamoDB tables when performing terraform plan
and terraform apply
NOTE: This module cannot be used to apply changes to the mfa_delete
feature of the bucket. Changes regarding mfa_delete can only be made manually using the root credentials with MFA of the AWS Account where the bucket resides. Please see: https://github.com/terraform-providers/terraform-provider-aws/issues/629
Usage
Create
Follow this procedure just once to create your deployment.
-
Add the
terraform_state_backend
module to yourmain.tf
file. The comment will help you remember to follow this procedure in the future:# You cannot create a new backend by simply defining this and then
# immediately proceeding to "terraform apply". The S3 backend must
# be bootstrapped according to the simple yet essential procedure in
# https://github.com/cloudposse/terraform-aws-tfstate-backend#usage
module "terraform_state_backend" {
source = "cloudposse/tfstate-backend/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "test"
name = "terraform"
attributes = ["state"]
terraform_backend_config_file_path = "."
terraform_backend_config_file_name = "backend.tf"
force_destroy = false
}
# Your Terraform configuration
module "another_module" {
source = "....."
}Module inputs
terraform_backend_config_file_path
andterraform_backend_config_file_name
control the name of the backend definition file. Note that whenterraform_backend_config_file_path
is empty (the default), no file is created. -
terraform init
. This downloads Terraform modules and providers. -
terraform apply -auto-approve
. This creates the state bucket and DynamoDB locking table, along with anything else you have defined in your*.tf
file(s). At this point, the Terraform state is still stored locally.Module
terraform_state_backend
also creates a newbackend.tf
file that defines the S3 state backend. For example:backend "s3" {
region = "us-east-1"
bucket = "< the name of the S3 state bucket >"
key = "terraform.tfstate"
dynamodb_table = "< the name of the DynamoDB locking table >"
profile = ""
role_arn = ""
encrypt = true
}Henceforth, Terraform will also read this newly-created backend definition file.
-
terraform init -force-copy
. Terraform detects that you want to move your Terraform state to the S3 backend, and it does so per-auto-approve
. Now the state is stored in the S3 bucket, and the DynamoDB table will be used to lock the state to prevent concurrent modification.
This concludes the one-time preparation. Now you can extend and modify your Terraform configuration as usual.
Destroy
Follow this procedure to delete your deployment.
- In
main.tf
, change theterraform_state_backend
module arguments as follows:module "terraform_state_backend" {
# ...
terraform_backend_config_file_path = ""
force_destroy = true
} terraform apply -target module.terraform_state_backend -auto-approve
. This implements the above modifications by deleting thebackend.tf
file and enabling deletion of the S3 state bucket.terraform init -force-copy
. Terraform detects that you want to move your Terraform state from the S3 backend to local files, and it does so per-auto-approve
. Now the state is once again stored locally and the S3 state bucket can be safely deleted.terraform destroy
. This deletes all resources in your deployment.- Examine local state file
terraform.tfstate
to verify that it contains no resources.
Bucket Replication (Disaster Recovery)
To enable S3 bucket replication in this module, set s3_replication_enabled
to true
and populate s3_replica_bucket_arn
with the ARN of an existing bucket.
module "terraform_state_backend" {
source = "cloudposse/tfstate-backend/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "test"
name = "terraform"
attributes = ["state"]
terraform_backend_config_file_path = "."
terraform_backend_config_file_name = "backend.tf"
force_destroy = false
s3_replication_enabled = true
s3_replica_bucket_arn = "arn:aws:s3:::eg-test-terraform-tfstate-replica"
}