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; keydev/terraform.tfstate. use_lockfile = true: the lock is an object next to the state, ending in.tflock. No DynamoDB.sensitivehides 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. Raisedata_wo_revisionto rotate. init -migrate-statecopies state to the new backend;init -reconfigurestarts 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. ReadLock Infobefore anything else. - Committing
terraform.tfstate: every secret it ever held stays in Git history.
Commands
terraform state show ADDRESS | Everything state records for one object |
terraform state pull | The whole state as JSON |
terraform init -migrate-state | Move state to the backend in backend.tf |
docker compose -f state/compose.yaml up -d | Start the state store |
set -a && . state/.env && set +a | Load 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.