2 minute read

Bootstrapping Terraform

An idea on how to bootstrap terraform projects, and keep a full track record of everything.


in
Terraform
Cloud-native

I have been working with Terraform for several years now on a number of projects. This is a short post explaining my preferred way of bootstrapping a brand new Terraform project for an organization.

A place for the Terraform state file

Each time we modify Terraform code, we effectively modify an internal state representation that Terraform has for our infrastructure. Terraform uses this state to generate the diffs that we review during terraform plan. This state often holds sensitive variables, such as account identifiers, temporary passwords or keys, or other information we don't wish to commit to version control.

Terraform uses a state backend to determine how the Terraform state is preserved, and supports a number of options from blob storage (such as AWS S3, as a Kubernetes secret, or simply a local file). If we use a remote backend such as S3 or Kubernetes, we can implement sufficient authorization and access control policies and our problem is mostly solved.

However to be able to use one of these remote backends (which you would consider pieces of infrastructure themselves) and if you are like me, you will prefer to also define the S3 bucket used to store the Terraform state in Terraform. This is now a chicken-and-egg problem - we want to store the state in a bucket, but to be able to create said bucket, we need an already-existing and configured Terraform project.

Let's use multiple projects

To solve our problem, we simply introduce another Terraform project. The sole purpose of this new Terraform project is to provision the AWS S3 bucket (and optionally DynamoDB table for state locking) so that the main project can be configured using these resources as the state backend. I typically put this inside a folder named bootstrap with a short README document on why it exists.

bootstrap/
  .terraform.lock.hcl
  bootstrap.tf
  bootstrap.tfstate
  README.Md
infra/
  .terraform.lock.hcl
  terraform.tf
  ...

The bootstrap project will use the local file backend, which we will commit to version control. Since neither the S3 bucket name or DynamoDB table name would be considered sensitive data, we should be OK with keeping them in version control. Once bootstrapped, the bootstrap Terraform project is likely not to be touched ever again (apart from Terraform provider version updates).

This leaves us with all resources declared using Terraform, and no pesky buckets manually created in the console.

This simple approach makes it really easy to destroy all the resources associated in the project if you go bankrupt and have to shut down too :)


Blog content licensed under CC BY-NC-SA 4.0 DEED.