PlatformEngr® Terraform course

Cheat notes · Module 03 · State, modules and environments

State: a shared backend, a lock, and the secrets inside

A five-minute review for when you have done this module and want it back in your head. Open the full module for the steps and the lab, or the full text to print.

The idea

State maps every address to a real object and stores all its attributes, secrets included, in plain text. A shared, locked backend lets a team use one state safely; keeping secrets out of it is a separate decision per secret.

Remember

  • Backend: where state lives. Here backend "s3" against a local S3-compatible store; key dev/terraform.tfstate.
  • use_lockfile = true: the lock is an object next to the state, ending in .tflock. No DynamoDB.
  • sensitive hides a value in output; it is still in state.
  • Ephemeral resource + write-only argument (ephemeral "random_password", data_wo): the value reaches the API and is never stored. Raise data_wo_revision to rotate.
  • init -migrate-state copies state to the new backend; init -reconfigure starts fresh and copies nothing.
  • Read access to the bucket is read access to every secret in state.

Pitfalls

  • Changing the key and running init -reconfigure: the plan wants to create everything that exists. Terraform is reading an empty state; put the key back.
  • A plan that waits on Error acquiring the state lock: someone else is writing. Read Lock Info before anything else.
  • Committing terraform.tfstate: every secret it ever held stays in Git history.

Commands

terraform state show ADDRESSEverything state records for one object
terraform state pullThe whole state as JSON
terraform init -migrate-stateMove state to the backend in backend.tf
docker compose -f state/compose.yaml up -dStart the state store
set -a && . state/.env && set +aLoad the store's credentials into this terminal

envs/dev/backend.tf

terraform {
  backend "s3" {
    bucket       = "tfstate"
    key          = "dev/terraform.tfstate"
    region       = "us-east-1"
    use_lockfile = true
  }
}

Plus six lines that only exist because the store is not AWS.

Test yourself

Answer in your head first, then open the answer.

Why not keep state in Git?

No lock, so two applies overwrite each other, and every secret stays in history.

What does sensitive = true protect against?

Showing the value in plans and outputs. Not storing it in state.

-migrate-state or -reconfigure: which copies the state?

-migrate-state.

How does data_wo keep a password out of state?

It is write-only: sent to the API on apply and never recorded; the value comes from an ephemeral resource.

Where module 03 leaves you: The state of envs/dev is the object dev/terraform.tfstate in the bucket tfstate, locked while anyone plans or applies. No state file is on disk or in Git. Secret checkout-db exists in checkout-dev and its value is not in the state. envs/dev/backend.tf and state/compose.yaml are committed; state/.env is not.