Since the dawn of time people have been dealing with Chicken and egg problems in terraform.

I need to create a resource, which is depended on by another resource, but the first resource depends on the last one

Imagine a circle.

One of the main issues I've come across when you start a new engagement with a client or a company where they don't use terraform is: How do I create state buckets

The solution can be as simple or as advanced as you want it to be. Let's explore some solutions:

I prefer to create a state bucket, then use CI to create more state buckets in terraform.

  • Command to create the first state bucket
  • Terraform in the repo

Command to create the first state bucket

Most cloud providers allow you to use their CLI, Google has  gcloud and Amazon has aws respectively to interact with the cloud provider.

This solution relies on you running a command. By doing this you get no state to check the bucket against, but the command is set and forget.

AWS:

REGION="us-east-1"
aws s3api create-bucket \
	--region "${REGION}" \
	--bucket "companyname-terraformstate-state" \

aws dynamodb create-table \
	--region "${REGION}" \
	--table-name companyname_terraformstate_state \
	--attribute-definitions AttributeName=LockID,AttributeType=S \
	--key-schema AttributeName=LockID,KeyType=HASH \
	--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
   

GCP

gsutil mb -c nearline gs://compantname-terraformstate-state

In GCP, state locking is done through the bucket opposed to needing a dynamoDB table.

You can then point your terraform repo/ directory for managing new state buckets to this bucket.

Terraform in the repo

This is the option I chose to go for, as it shows the bucket was created and you've got state for that bucket so you can look and see how the bucket was configured. A nice touch of this is that you can then scan it with things like tfsec and checkov

Because I am a GCP engineer, this will be a GCP example but I am sure chatGPT will be able to convert the below in to your cloud provider of choice

resource "google_storage_bucket" "bucket" {
  location                    = "europe-west2"
  name                        = "companyname-terraformstate-state
  project                     = "companyname-terraform-state"
  public_access_prevention    = "enforced"
  storage_class               = "STANDARD"
  uniform_bucket_level_access = true
  force_destroy               = false
  versioning {
    enabled = true
  }

  lifecycle_rule {
    action {
      type = "Delete"
    }
    condition {
      num_newer_versions = 100
      with_state         = "ARCHIVED"
    }
  }

  lifecycle_rule {
    action {
      type = "Delete"
    }
    condition {
      days_since_noncurrent_time = 100
      with_state                 = "ANY"
    }
  }

}

You will then run the below commands

terraform plan
terraform apply
git add terraform.tfstate
git add .
git commit -m 'Configuring state bucket for other state'
git push

You're now free to use this bucket for holding the central state for terraform to provision other state


If you need help with configuring terraform state, reach out and we can work together on a solution!