Terraform state in AWS S3

Managing Terraform state in AWS S3 bucket. Create S3 bucket for storing the Terraform state and DynamoDB for keep the Terraform lock.

Jan 25, 2023

Managing Terraform state in AWS S3 bucket. Create S3 bucket for storing the Terraform state and DynamoDB for keep the Terraform lock.

Resources

  1. AWS KMS key
  2. S3 bucket
  3. S3 bucket server side encryption
  4. S3 bucket acl and block public access
  5. S3 bucket versioning
  6. DynamoDB table

Create S3 bucket and DynamoDB table

terraform.tfvars

bucket_name = "terraform-backend-state"

main.tf

variable "bucket_name" {
  type        = string
  description = "Bucket name to hold terraform state"
}

resource "aws_kms_key" "tf" {
  description             = "KMS Key to encrypt Terraform state and lock"
  deletion_window_in_days = 7
}

resource "aws_s3_bucket" "bucket" {
  bucket = var.bucket_name

  tags = {
    Name = var.bucket_name
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "encrypt" {
  bucket = aws_s3_bucket.bucket.id

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.tf.id
      sse_algorithm     = "aws:kms"
    }
  }
}

resource "aws_s3_bucket_acl" "acl" {
  bucket = aws_s3_bucket.bucket.id
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "block_public" {
  bucket = aws_s3_bucket.bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "enable" {
  bucket = aws_s3_bucket.bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_dynamodb_table" "tf_state" {
  name         = "TerraformState"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"
  attribute {
    name = "LockID"
    type = "S"
  }

  server_side_encryption {
    enabled = true
    kms_key_arn = aws_kms_key.tf.arn
  }

  tags = {
    Name = "TerraformState"
  }
}

Configure the backend in Terraform

state.tf

terraform {
  backend "s3" {
    bucket         = "terraform-backend-state"
    key            = "development/us-east-1/my-website/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "TerraformState"
  }
}