5/6/2023 7:38:05 PM

DONT STORE TERRAFORM STATE IN GITHUB! DONT STORE TERRAFORM STATE IN GITHUB! DONT STORE TERRAFORM STATE IN GITHUB! DONT STORE TERRAFORM STATE IN GITHUB!

Well, that's what everyone says. And it's true, you shouldn't. If you're a solo developer, you probably don't have to worry but, still, you shouldn't do it. But what should you do? My preferred solution is to use AWS S3 and AWS DynamoDb. And fortunately, it is very easy to do.

The basic setup for this is the following.

  • * First, we are assuming you are using Terraform to make changes to your AWS infrastructure. This means you already have an AWS IAM User with permissions that you use in Terraform. If not, you will need to create a user and attach permissions.
  • * Secondly, we are also assuming that the AWS user you are using in Terraform is referenced via an AWS profile name. That means the AWS Access Key and Secret Key are stored in the .aws\credentials file, not anywhere in your Terraform project.
  • Create a Bucket in S3 to store Terraform state data.
    ex: my-project-name--terraform
  • Create a DynamoDb table for each Environment to store Terraform lock data. The Partition Key/Hash Key for this table must be "LockID" of type String (case matters).
    ex: my-project-name--dev--terraform-locks
    ex: my-project-name--prod--terraform-locks
  • Update the your Terraform AWS User's permissions.
    { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:PutObject", "dynamodb:DescribeTable", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem" ], "Resource": [ "arn:aws:dynamodb:::table/my-project-name--dev--terraform-locks", "arn:aws:dynamodb:::table/my-project-name--prod--terraform-locks", "arn:aws:s3:::my-project-name--terraform/*", "arn:aws:s3:::my-project-name--terraform" ] }
  • Create a Terraform file for each Environment to specify where to store Terraform state data. This file can be named anything with a ".tf" extension. Lets name it "backend.tf". It will be placed in an Environment specific folder. For us, that is a folder named "dev" or "prod" in the root of our Terraform project. You have to create this file for each environment and correctly set the bucket key and DynamoDb table name specific to each environment.
    ex: ./prod/backend.tf
    terraform { backend "s3" { bucket = "my-project-name--terraform" key = "prod/terraform.tfstate" region = "us-east-1" dynamodb_table = "my-project-name--prod--terraform-locks" profile = "aws_user_profile_name" } }
  • Run a Terraform command to begin state migration.
    terraform init