Terraform modules
What a module is
Any directory of .tf files is a module. The directory you run Terraform in is the root module; anything invoked with a module block is a child module. Modules package reusable, versioned infrastructure behind a narrow input/output contract.
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.5.1"
cidr = "10.0.0.0/16"
}
output "vpc_id" { value = module.vpc.vpc_id }
Mechanics
sourcesupports the public/private registry, Git URLs (git::https://host/repo.git?ref=v1.2.0), object storage buckets, and local paths (./modules/network).versionis honored only for registry-style sources; local paths and raw Git use?ref=instead.- Inputs are the child's declared variables; outputs are read as
module.<name>.<output>. A child's internal resources are never addressable from the parent. terraform initinstalls modules into.terraform/modules; changingsourceorversionrequiresinit, andinit -upgrademoves to newer allowed versions.- Modules accept
countandfor_each, producing addresses likemodule.vpc["prod"].vpc_id. - Pass aliased providers explicitly:
providers = { aws = aws.west }.
Traps
- Declaring a provider block inside a reusable module is discouraged; the root should configure and pass providers.
- A module output must be explicitly declared - forgetting it is the classic "why can't the parent see this attribute" bug.
- A
versionargument on a local-path module is silently meaningless, not an error worth relying on.
Rule of thumb
If you are copy-pasting the same resource block into a second environment, that block belongs in a module with variables for what differs.