5.1.1. Module Concepts and Sources
💡 First Principle: The source argument is a mini-protocol selector — its prefix tells Terraform whether to copy a local folder, clone a Git repo, or download from a registry — which is why the same module block works regardless of where the code lives.
A module is a container for resources used together. The directory where you run Terraform is the root module; modules it calls are child modules. You call a child with a module block whose source argument names where to find it:
module "network" {
source = "./modules/network" # local path
vpc_cidr = "10.0.0.0/16" # input to the child's variables
}
Supported source types include local paths (must start with ./ or ../), the Terraform Registry (namespace/name/provider), Git (git::https://... or github.com/org/repo), generic HTTP URLs, and cloud storage like S3 (s3::) and GCS (gcs::). Running terraform init installs all referenced modules into the .terraform directory.
⚠️ Exam Trap: Local module sources must begin with ./ or ../. A bare path like modules/network is interpreted as a registry address, not a local folder — a classic init failure. Also note init is required after adding or changing a module source.
Reflection Question: Why does Terraform need the ./ prefix to distinguish a local module from a registry module, given both are just strings?