Suppose a Terraform configuration must deploy an application using separate modules for its network-facing components, container service, database, and cache. The root module is the entry point that assembles those pieces. It can pass one module’s outputs into another module’s inputs and expose settings that vary by environment. section 8.4
A module is a collection of related resources, data sources, and supporting assets. The root module is the module Terraform starts from, not a particular location in a repository. When you run terraform init or terraform apply, the .tf files in the current working directory make up that root module. It may contain resources directly, call other modules, or do both. section 3.1 section 3.1.3
Keep the responsibilities of the entry point distinct from those of a reusable module:
- Configure providers in the root module. A reusable module can declare required providers, but its provider configuration blocks must be removed when refactoring it for reuse. section 3.1.3 section 3.8.1
- Accept values supplied by the person running a plan or apply at the root, then pass the needed values to child modules. section 8.4
- Choose the root by how the configuration is called, not by its repository path. A reusable application module can itself serve as a root, or another root can call it. section 3.8.1 section 8.4
One root per environment
Create staging/main.tf and production/main.tf as separate entry points. Each can be a thin wrapper that calls the same application module while selecting its own module version and environment settings. This keeps deployments independent without requiring one shared root to handle every environment. section 8.4.2
Listing 8.10 Environment main.tf example
variable "logging_api_key" { #1
sensitive = true #2
}
module "application" { #3
source = "registry.example.com/example/aws/application"
version = "1.1.1" #4
network_name = "dev_network" #5
db_size = 20 #5
num_tasks = 5 #5
logging_api_key = var.logging_api_key #6
}
output "application_url" { #7
value = module.application.url
}
This environment root pins an application module version, supplies network and capacity settings, passes a sensitive logging key through a variable, and exposes the application URL as an output. Keep sensitive values out of settings committed to source control. section 8.4.2
