Terraform Root Modules

Collection of Terraform Root Module invocations

We practice a pattern we call terraform-root-modules which is where we implement fully working invocations of modules designed to be used at the “root” level. Terraform defines a “root module” as the current working directory holding the Terraform configuration files where the terraform apply or terraform get is run. That is, terraform considers the entry point itself a valid module.

Our strategy is to define various common patterns that we use in our cloud infrastrucutres and codify them as “reference architectures”. We build a docker image of the terraform-root-modules repo and tag regular releases, so it’s possible to literally do COPY --from=terraform-root-modules in our geodesic modules using the docker multi-stage build convention.

Here’s what it looks like in practice: (only relevant portions)

Dockerfile Snippet

FROM cloudposse/terraform-root-modules:0.1.5 as terraform-root-modules

FROM cloudposse/geodesic:0.9.16

# ...

# Copy root modules
COPY --from=terraform-root-modules /aws/tfstate-backend/ /conf/tfstate-backend/
COPY --from=terraform-root-modules /aws/chamber/ /conf/chamber/
COPY --from=terraform-root-modules /aws/cloudtrail/ /conf/cloudtrail/

We use this strategy for several reasons:

  1. Private Repos It let’s us get around challenges of doing a git clone during a docker build, since most organizations will not make their “root modules” public the way we do.
  2. No Wrappers Needed Using multi-stage builds let’s us avoid needing to use a wrapper cli like terragrunt.
  3. Reusable Pattern It works for not just terraform, but any use-case where infrastructure should be versioned and copied/staged across multiple repositories