DevOps Peach

Advanced Terraform · Environments, Import and Drift · Lesson 2 of 4

Environment Layout and Variable Precedence

Keep logic in versioned modules, keep each environment a thin root folder with its own tfvars and backend, and know the order in which variable values override each other.

Practice interactively →

A layout that scales keeps the logic in modules and makes each environment a thin root module: a backend, provider settings, one or two module calls and a tfvars file.

flowchart TB
  MOD["modules/app (v1.6.0)"] --> DEV["envs/dev: main.tf, dev.tfvars"]
  MOD --> STG["envs/staging"]
  MOD --> PRD["envs/prod (pinned v1.5.2)"]
  DEV --> BD["backend key dev/app.tfstate"]
  PRD --> BP["backend key prod/app.tfstate"]
  %% step MOD: The module holds the real logic and is released with version tags.
  %% step DEV: Dev uses the newest module version first and has small sizes in its tfvars.
  %% step STG: Staging follows, with the same code as prod will get.
  %% step PRD: Prod pins an older tag until the new one is proven, then bumps it in a pull request.
  %% step BP: Each environment has its own state and can have its own account and role.
infra/
  modules/app/            # or a separate repo with tags
  envs/
    dev/      main.tf  backend.tf  dev.tfvars
    staging/  main.tf  backend.tf  staging.tfvars
    prod/     main.tf  backend.tf  prod.tfvars
# envs/prod/main.tf
module "app" {
  source   = "git::https://github.com/example-org/tf-modules.git//app?ref=v1.5.2"
  env      = "prod"
  replicas = var.replicas
}

Run each environment from its folder (cd envs/prod) or with the global option terraform -chdir=envs/prod plan.

Variable precedence

When the same variable is set in several places, the last one in this list wins:

Order Source
1 (lowest) default in the variable block
2 Environment variable TF_VAR_replicas=2
3 terraform.tfvars
4 terraform.tfvars.json
5 *.auto.tfvars / *.auto.tfvars.json, in alphabetical order
6 (highest) -var and -var-file on the command line, in the order you type them

terraform.tfvars and *.auto.tfvars load automatically; any other file (prod.tfvars) needs -var-file. In CI, TF_VAR_ environment variables are handy for values that come from the pipeline, but never for long-lived secrets that end up in logs.

Keep environments honest

Traps: an old terraform.tfvars in the folder silently overrides TF_VAR_ values; and -chdir must come before the subcommand (terraform -chdir=envs/dev plan, not terraform plan -chdir=...).

Practice interactively →