
A Terraform module is a collection of configuration files that encapsulate resources used together to achieve a specific outcome. Modules promote reusability, organization, and maintainability in infrastructure as code by allowing you to group related resources and manage them as a single unit.
Understanding the Module Block
In Terraform, you define a module block to incorporate the contents of another module into your configuration. This allows you to reuse existing configurations and standardize resource provisioning across your infrastructure.
Syntax of a Module Block
A typical module block has the following structure:
module "<MODULE_NAME>" {
source = "<SOURCE>"
version = "<VERSION>"
# Additional arguments corresponding to the module's input variables
}
๎
<MODULE_NAME>
: A unique identifier for the module instance within your configuration.<SOURCE>
: Specifies the location of the moduleโs source code. This can be a local path, a Git repository, or a Terraform Registry address.<VERSION>
: Defines the version of the module to use, applicable when sourcing modules from registries.
Example: Using a Module from the Terraform Registry
Suppose you want to deploy an AWS Virtual Private Cloud (VPC) using a community-maintained module from the Terraform Registry. You can define the module block as follows:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.19.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-west-1a", "us-west-1b", "us-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
In this example:
source
: Specifies the moduleโs location in the Terraform Registry.version
: Ensures that Terraform uses version 3.19.0 of the module, maintaining consistency across deployments.- The subsequent arguments (
name
,cidr
,azs
, etc.) correspond to the input variables defined by the module, allowing customization of the VPCโs configuration.
Example: Using a Local Module
You can also create and reference local modules within your project directory. Assume you have a module that sets up an AWS EC2 instance, located in the modules/ec2-instance
directory:
module "web_server" {
source = "./modules/ec2-instance"
instance_type = "t2.micro"
ami_id = "ami-0c55b159cbfafe1f0"
subnet_id = "subnet-abc12345"
}
๎
Here:
source
: Points to the relative path of the local module.- The arguments (
instance_type
,ami_id
,subnet_id
) are input variables defined within theec2-instance
module, allowing you to customize the EC2 instanceโs properties.๎
Key Components of a Module
A well-structured Terraform module typically includes the following files:๎
main.tf
: Contains the primary resource definitions.๎variables.tf
: Declares input variables to parameterize the module.๎outputs.tf
: Defines output values to expose information about the resources.๎versions.tf
: Specifies the required Terraform version and provider constraints.๎README.md
: Provides documentation on the moduleโs purpose and usage.๎
Best Practices for Using Modules
- Encapsulation: Modules should encapsulate their resources, exposing only necessary inputs and outputs.๎
- Reusability: Design modules to be reusable across different configurations and environments.๎
- Versioning: Implement version control for modules to manage changes and ensure stability.๎
- Documentation: Provide clear documentation within the module directory to explain its purpose and usage.๎
- Consistency: Use consistent naming conventions and file structures across modules.๎
By effectively utilizing module blocks, you can create modular, reusable, and maintainable infrastructure configurations, enhancing the scalability and manageability of your Terraform projects.
$ tree minimal-module/
.
โโโ README.md
โโโ main.tf
โโโ variables.tf
โโโ outputs.tf
module "consul" { | |
source = "hashicorp/consul/aws" | |
} | |
module "moduleName" { | |
source = "module/path" | |
} | |
module "networkModule" { | |
source = "./module/network" | |
} | |
module "s3-bucket" { | |
source = "terraform-aws-modules/s3-bucket/aws" | |
version = "1.0.0" | |
# insert the 6 required variables here | |
} | |
Working with Terraform Modules | |
=================================== | |
$ terraform init | |
# Add modules in .tf | |
$ terraform get | |
$ terraform plan | |
$ terraform apply | |
$ terraform show |
resource "azurerm_resource_group" "example" {
name = "my-resources66"
location = "West Europe"
}
module "apache"{
source = "./modules/install_apache"
}
module "nginx"{
source = "./modules/install_nginx"
instances = ["${module.web.instance_ids}"]
}
module "network" {
source = "Azure/network/azurerm"
resource_group_name = azurerm_resource_group.example.name
address_spaces = ["10.0.0.0/16", "10.2.0.0/16"]
subnet_prefixes = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
subnet_names = ["subnet1", "subnet2", "subnet3"]
subnet_service_endpoints = {
"subnet1" : ["Microsoft.Sql"],
"subnet2" : ["Microsoft.Sql"],
"subnet3" : ["Microsoft.Sql"]
}
tags = {
environment = "dev"
costcenter = "it"
}
depends_on = [azurerm_resource_group.example]
}
key parameters available for a Terraform module
block
Certainly! Hereโs a table summarizing the key parameters available for a Terraform module
block:
Parameter | Description | Required | Example |
---|---|---|---|
source | Specifies the location of the moduleโs source code. This can be a local path, a Git repository, or a Terraform Registry address. | Yes | source = "./modules/network" or source = "terraform-aws-modules/vpc/aws" |
version | Defines the version of the module to use, particularly when sourcing modules from registries. | No | version = "3.0.0" |
providers | Overrides the default provider configurations for the module. Useful when you need to specify different provider settings for a particular module. | No | providers = { aws = aws.us_east } |
count | Creates multiple instances of the module. Allows you to scale resources by specifying the number of instances. | No | count = 3 |
for_each | Creates multiple instances of the module based on a map or set of strings. Provides more control compared to count , especially when each instance requires unique configurations. | No | for_each = { net1 = "10.0.0.0/16", net2 = "10.1.0.0/16" } |
depends_on | Specifies dependencies on other resources or modules. Ensures that the module is provisioned only after certain resources or modules have been created. | No | depends_on = [aws_vpc.main] |
*Note: Input variables are user-defined parameters that allow customization of the moduleโs behavior. Each input variable must be defined within the moduleโs variables.tf
file. When calling the module, you provide values for these variables.*๎
By utilizing these parameters, you can effectively manage and customize the behavior of your Terraform modules, leading to more modular and maintainable infrastructure configurations.
In Terraform, a module block is used to incorporate the configuration of one module into another, promoting reusability and organization in your infrastructure as code. The module
block supports several parameters, allowing you to customize its behavior and the resources it provisions. Here's a breakdown of the key parameters you can define within a module
block:
-
source
(Required):- Description: Specifies the location of the module's source code.
- Usage: This can be a local file path, a URL to a version control system (like Git), or a reference to a module in the Terraform Registry.
- Example:
or
module "network" { source = "./modules/network" }
module "network" { source = "terraform-aws-modules/vpc/aws" }
-
version
(Optional):- Description: Specifies the version of the module to use.
- Usage: Particularly useful when sourcing modules from the Terraform Registry to ensure compatibility and stability.
- Example:
module "network" { source = "terraform-aws-modules/vpc/aws" version = "3.0.0" }
-
Input Variables:
- Description: These are user-defined parameters that allow customization of the module's behavior.
- Usage: Each input variable must be defined within the module's
variables.tf
file. When calling the module, you provide values for these variables. - Example:
Here,
module "network" { source = "./modules/network" cidr = "10.0.0.0/16" region = "us-west-1" }
cidr
andregion
are input variables defined within thenetwork
module.
-
providers
(Optional):- Description: Overrides the default provider configurations for the module.
- Usage: Useful when you need to specify different provider settings for a particular module.
- Example:
provider "aws" { region = "us-west-1" } module "network" { source = "./modules/network" providers = { aws = aws.us_east } } provider "aws" { alias = "us_east" region = "us-east-1" }
-
count
(Optional):- Description: Creates multiple instances of the module.
- Usage: Allows you to scale resources by specifying the number of instances.
- Example:
This will instantiate the
module "network" { source = "./modules/network" count = 3 }
network
module three times.
-
for_each
(Optional):- Description: Creates multiple instances of the module based on a map or set of strings.
- Usage: Provides more control compared to
count
, especially when each instance requires unique configurations. - Example:
This will create two instances of the
module "network" { source = "./modules/network" for_each = { net1 = "10.0.0.0/16" net2 = "10.1.0.0/16" } cidr = each.value }
network
module with different CIDR blocks.
-
depends_on
(Optional):- Description: Specifies dependencies on other resources or modules.
- Usage: Ensures that the module is provisioned only after certain resources or modules have been created.
- Example:
Here, the
module "network" { source = "./modules/network" depends_on = [aws_vpc.main] }
network
module will be created only after theaws_vpc.main
resource is provisioned.
By utilizing these parameters, you can effectively manage and customize the behavior of your Terraform modules, leading to more modular and maintainable infrastructure configurations.
Terraform Module Block Source Arguments Style
In Terraform, the source
argument within a module block specifies the location of the module's source code. Terraform supports various methods to define this source, allowing flexibility in module sourcing. Here are the different ways to specify the source
parameter, along with examples:
1. Local Paths
You can reference modules stored locally on your filesystem using relative paths.
module "network" {
source = "./modules/network"
# Additional module arguments
}
In this example, Terraform will load the module from the modules/network
directory relative to your current working directory.
2. Terraform Registry
Modules can be sourced directly from the Terraform Registry, which hosts a vast collection of publicly available modules.
module "consul" {
source = "hashicorp/consul/aws"
version = "0.0.5"
# Additional module arguments
}
Here, the Consul module for AWS is sourced from the Terraform Registry. Specifying the version
ensures that Terraform uses the desired module version. ๎cite๎turn0search6
3. GitHub
Modules can be sourced from GitHub repositories using the github.com
prefix.
module "vpc" {
source = "github.com/terraform-aws-modules/terraform-aws-vpc"
# Additional module arguments
}
This example fetches the VPC module from the specified GitHub repository. ๎cite๎turn0search0
4. Generic Git Repositories
Terraform supports sourcing modules from any Git repository by specifying the repository URL.
module "vpc" {
source = "git::https://example.com/terraform-modules.git//vpc?ref=tags/v0.1.0"
# Additional module arguments
}
In this case, Terraform retrieves the vpc
module from the specified Git repository at the v0.1.0
tag. ๎cite๎turn0search0
5. Bitbucket
Modules can also be sourced from Bitbucket repositories.
module "vpc" {
source = "bitbucket.org/organization/terraform-modules.git//vpc?ref=tags/v0.1.0"
# Additional module arguments
}
This example fetches the vpc
module from a Bitbucket repository at the specified tag. ๎cite๎turn0search0
6. HTTP URLs
Modules can be downloaded from HTTP URLs pointing to a ZIP archive of the module.
module "network" {
source = "https://example.com/terraform-modules/network.zip"
# Additional module arguments
}
Terraform will download and extract the module from the specified URL. ๎cite๎turn0search0
7. Amazon S3 Buckets
Modules stored in Amazon S3 buckets can be referenced directly.
module "network" {
source = "s3::https://s3.amazonaws.com/mybucket/terraform-modules/network.zip"
# Additional module arguments
}
Here, Terraform retrieves the module from the specified S3 bucket. ๎cite๎turn0search0
8. Google Cloud Storage (GCS) Buckets
Similarly, modules can be sourced from GCS buckets.
module "network" {
source = "gcs::https://storage.googleapis.com/mybucket/terraform-modules/network.zip"
# Additional module arguments
}
Terraform will download the module from the specified GCS bucket. ๎cite๎turn0search0
Note on Parameterizing the source
Argument
As of Terraform v0.13, the source
argument must be a literal string and cannot directly reference variables or expressions. This design ensures that module sources are known before evaluating the configuration. ๎cite๎turn0search6
By utilizing these methods, you can flexibly source Terraform modules from various locations, tailoring your infrastructure as code to your project's needs.
In Terraform, you can specify a module's source using various Git options to control which version or part of the repository to use. Here are examples illustrating different scenarios:
1. Default Branch
By default, Terraform fetches the module from the repository's default branch (usually main
or master
):
module "network" {
source = "git::https://github.com/username/repository.git"
# Additional module arguments
}
2. Specific Branch
To use a specific branch, append the ref
parameter with the branch name:
module "network" {
source = "git::https://github.com/username/repository.git?ref=branch-name"
# Additional module arguments
}
3. Specific Tag
To use a specific tag, set the ref
parameter to the tag name:
module "network" {
source = "git::https://github.com/username/repository.git?ref=v1.0.0"
# Additional module arguments
}
4. Specific Commit ID
To use a specific commit, set the ref
parameter to the commit hash:
module "network" {
source = "git::https://github.com/username/repository.git?ref=commit-sha"
# Additional module arguments
}
5. Subdirectory in a Specific Branch
If the module resides in a subdirectory of a specific branch, specify both the branch and the subdirectory:
module "network" {
source = "git::https://github.com/username/repository.git//subdirectory?ref=branch-name"
# Additional module arguments
}
6. SSH Protocol
To clone a private repository over SSH, use the SSH URL:
module "network" {
source = "git::ssh://git@github.com/username/repository.git"
# Additional module arguments
}
7. GitHub Shortcut
For public GitHub repositories, you can use a shorthand notation:
module "network" {
source = "github.com/username/repository"
# Additional module arguments
}
8. Git Over SSH with Subdirectory
To access a module in a subdirectory over SSH:
module "network" {
source = "git::ssh://git@github.com/username/repository.git//subdirectory"
# Additional module arguments
}
9. Git Over HTTPS with Authentication
For private repositories over HTTPS, include the username and token:
module "network" {
source = "git::https://username:token@github.com/username/repository.git"
# Additional module arguments
}
10. Bitbucket Repository
To source a module from a Bitbucket repository:
module "network" {
source = "git::https://bitbucket.org/username/repository.git"
# Additional module arguments
}
11. GitLab Repository
To source a module from a GitLab repository:
module "network" {
source = "git::https://gitlab.com/username/repository.git"
# Additional module arguments
}
12. Using a Depth Parameter for Shallow Clone
To perform a shallow clone and limit the history depth:
module "network" {
source = "git::https://github.com/username/repository.git?ref=branch-name&depth=1"
# Additional module arguments
}
By utilizing these Git options, you can precisely control which version or part of a repository Terraform uses for your modules.










Iโm a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I am working at Cotocus. I blog tech insights at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at I reviewed , and SEO strategies at Wizbrand.
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at PINTEREST
Rajesh Kumar at QUORA
Rajesh Kumar at WIZBRAND