How do you store the state of the initial bootstrapping resources needed for remote state?

How do you store the state of the initial bootstrapping resources needed for remote state (in my case a single S3 bucket and a DynamoDB table for locking). It obviously can’t be managed using a remote state (turtles all the way down).

  1. Do you create it manually in $CLOUD_PROVIDER ?
  2. Do you keep a bootstrap project with also containing the tfstate file in git?
  3. Do you just use manage the bootstrapping .tf files in git and fire and forget (no storing of state)?

Any other suggestions?

What is the risk storing the tfstate file in git for a single S3 bucket and DynamoDB locking table?

In the past I’ve gone the bootstrap-config-and-tfstate-in-a-repo path. Today I would use remote state storage in Terraform Cloud.

This is a good question! There isn’t really a hard set pattern for doing this, but I do think Terraform Cloud is a good option. Regarding number 2, I would keep note that the tfstate could contain sensitive information, so I’d double check before storing that in any type of source control :slight_smile:

Any solutions/ideas other then Terraform Cloud?

I’ve seen a local state file committed to revision control (about the only appropriate use case I can think of besides demo code) and also the state sent to /dev/null since a terraform destroy on the S3 bucket would be catastrophic (per former HC employee James Nugent in a Hashidays NYC 2017 talk).

If Terraform Cloud is not a suitable solution for your first-level bootstrapping configuration (which would ideally only contain the infrastructure needed to support other separate Terraform configurations), there is a multi-step bootstrapping process you can follow to store the state of your first-level configuration inside the infrastructure it manages:

  1. Write the configuration with no backend block at all, but including the infrastructure required for whatever backend you eventually intend to use. For example, if you intend to use the s3 backend then you’ll have at least an aws_s3_bucket resource and probably also an aws_dynamodb_table resource, and also probably some IAM policy resources.
  2. Run terraform apply to create the described infrastructure and write its state into the local file terraform.tfstate.
  3. Now add the backend block for your chosen backend to the configuration and re-run terraform init. Terraform will offer to migrate the existing state snapshot into the new backend. Tell it to do so, and then the state will be stored in the remote backend.
  4. After this, use Terraform normally.

This bootstrapping workflow assumes that the infrastructure you use for the chosen backend will be managed in a separate configuration containing only that, and that you intend to provision it once and leave it provisioned forever. If you do end up needing to reprovision the storage container where the state snapshots are kept, you’ll need to do a similar multi-step process to ensure that Terraform is able to access the state at all steps.

Once your backend infrastructure is provisioned, you can then write other Terraform configurations as normal and immediately configure them to use that backend infrastructure, so the extra manual steps only apply to the special configuration that manages the backend infrastructure itself.