Terraform Tutorial · Modules and Quality · Lesson 21 of 25
Terraform Modules
Modules package configuration for reuse. Learn to write a module with inputs and outputs, call it, version it, and use modules from the Terraform Registry.
What is a module?
Every directory of .tf files is a module. The one you run terraform in is the root module; modules it
calls are child modules. A module is like a function: variables are its inputs, outputs its return values.
# file: main.tf
module "naming" {
source = "./modules/naming"
project = "shop"
environment = "prod"
}
output "bucket_name" {
value = module.naming.bucket_name
}
# file: modules/naming/main.tf
variable "project" {
type = string
}
variable "environment" {
type = string
}
output "bucket_name" {
value = "${var.project}-${var.environment}-assets"
}
Output
bucket_name = "shop-prod-assets"
Run this on your computer — see “Get Started” for setup.
Calling a module
module "network" {
source = "./modules/network" # a local path
cidr_block = "10.0.0.0/16"
environment = var.environment
}
resource "aws_instance" "app" {
subnet_id = module.network.private_subnet_ids[0]
# ...
}
Registry and Git modules
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
# ...
}
module "tagging" {
source = "git::https://github.com/acme/tf-modules.git//tagging?ref=v1.4.0"
}
Always pin a version (version for registry modules, ?ref= for Git) so upgrades are deliberate.
Good module design
- One clear job (a network, a database, a service), not "everything".
- Few, well-described variables with sensible defaults and validation.
- Outputs for everything a caller might need.
- No provider blocks inside reusable modules: let the caller configure providers.
Test yourself
How do you read output vpc_id from a module named network?
network.vpc_idmodule.network.vpc_idoutput.network.vpc_idvar.network.vpc_id
Show answer
Answer: module.network.vpc_id