Skip to main content

Command Palette

Search for a command to run...

Day 19: Module Sources & Versioning

Updated
5 min read
Day 19: Module Sources & Versioning
S

I'm a cloud-native enthusiast and tech blogger, sharing insights on Kubernetes, AWS, CI/CD, and Linux across my blog and Facebook page. Passionate about modern infrastructure and microservices, I aim to help others understand and leverage cloud-native technologies for scalable, efficient solutions.

Welcome to Day 19!
Today, we’ll dive deep into how to manage, version, and share Terraform modules effectively — one of the most important skills for creating scalable and maintainable infrastructure.

By the end of today, you’ll know exactly how to:
✅ Use modules from different sources (local, Git, S3, etc.)
✅ Apply versioning best practices
✅ Manage dependencies between modules
✅ Publish and share your own reusable modules
✅ Upgrade modules safely in production


🎯 Today’s Learning Objectives

  • Understand different Terraform module sources

  • Learn semantic versioning and version constraints

  • Use modules from the Terraform Registry

  • Handle dependencies between modules

  • Publish and upgrade your own Terraform modules safely


📚 1. Terraform Module Sources Explained

Terraform allows you to use modules from various sources—from your local filesystem to GitHub, Bitbucket, S3, and even Terraform Registry.

Let’s go through each type with examples. 👇


🔹 1. Local Modules

These are modules stored locally on your computer or within your project directory.

module "vpc" {
  source = "./modules/vpc"  # Local relative path
}

module "network" {
  source = "../shared-modules/network"  # Parent directory
}

module "app" {
  source = "/absolute/path/to/module"   # Absolute path
}

💡 Use case:

  • You’re developing custom modules for your project

  • You’re testing module changes quickly

  • You’re working in a single repo (monorepo)


🔹 2. Terraform Registry Modules

These are prebuilt community or official modules available on Terraform Registry.

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.2"
}

Format:
<NAMESPACE>/<MODULE_NAME>/<PROVIDER>

💡 Use case:

  • Want reliable, production-tested modules

  • Want to save time and follow AWS best practices

  • Example: terraform-aws-modules/vpc/aws, terraform-aws-modules/eks/aws


🔹 3. GitHub Modules

You can pull modules directly from GitHub via HTTPS, SSH, or specific version references.

# HTTPS
module "vpc" {
  source = "github.com/terraform-aws-modules/terraform-aws-vpc"
}

# Specific version (tag or branch)
module "vpc" {
  source = "github.com/terraform-aws-modules/terraform-aws-vpc?ref=v5.1.2"
}

# Subdirectory
module "example" {
  source = "github.com/hashicorp/terraform-aws-consul//modules/consul-cluster?ref=v0.11.0"
}

💡 Use case:

  • Using custom internal modules hosted on GitHub

  • Need fine-grained version control via Git tags

  • Want to contribute or fork existing modules


🔹 4. Generic Git Repositories

You can use any Git server (GitLab, private repo, etc.):

module "vpc" {
  source = "git::https://gitlab-stackopsdiary.site/vpc.git?ref=v1.2.0"
}

💡 Use case:

  • Enterprise teams hosting private infrastructure modules

🔹 5. S3, and HTTP Sources

You can also store your modules as ZIP archives in cloud storage or URLs.

S3 Example:

module "vpc" {
  source = "s3::https://s3-eu-west-1.amazonaws.com/company-modules/vpc-1.2.3.zip"
}

💡 Use case:

  • Hosting private modules for secure internal distribution

  • Integrating modules in CI/CD pipelines


🏷️ 2. Module Versioning (SemVer Explained)

🧩 Semantic Versioning (SemVer)

Terraform follows Semantic Versioning (MAJOR.MINOR.PATCH).

v1.2.3
 │ │ │
 │ │ └─ PATCH: Bug fixes (no breaking changes)
 │ └─── MINOR: Backward-compatible features
 └───── MAJOR: Breaking changes

So if a module goes from v2.3.1 → v3.0.0, it likely introduces breaking changes.


⚙️ Version Constraints

You can define how Terraform should handle module versions:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0" # Allows 5.x versions but not 6.x
}
ConstraintMeaning
= 5.1.2Exact version
>= 5.0.0Any version 5.0.0 or newer
~> 5.0\>=5.0, <6.0
~> 5.1.0\>=5.1.0, <5.2.0
!= 5.1.0Exclude version 5.1.0

✅ Best Practices

Do:

  • Always pin versions for production

  • Use ~> for minor auto-updates

  • Document module version requirements

Don’t:

  • Leave version unpinned

  • Use latest without testing

  • Jump to major versions blindly


🌐 3. Using Terraform Registry Modules

The Terraform Registry is like a module marketplace.

Steps:

  1. Go to registry.terraform.io

  2. Search, e.g., “aws vpc.”

  3. Review downloads, provider support, last update, and documentation

Example: VPC + Security Group + RDS

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
  name    = "my-vpc"
  cidr    = "10.0.0.0/16"
}
module "web_sg" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "~> 5.0"
  vpc_id  = module.vpc.vpc_id
}
module "db" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 6.0"
  engine  = "postgres"
}

These modules are battle-tested, frequently updated, and follow AWS best practices.


🔄 4. Managing Module Dependencies

Modules often depend on each other — e.g., your EC2 needs a VPC ID.

🔸 Implicit Dependency

Terraform automatically detects it when outputs are referenced:

module "vpc" {
  source = "./modules/vpc"
}

module "ec2" {
  source = "./modules/ec2"
  vpc_id = module.vpc.vpc_id  # Dependency created here
}

🔸 Explicit Dependency

You can also manually define dependencies:

module "monitoring" {
  source = "./modules/monitoring"
  depends_on = [module.vpc, module.ec2]
}

📦 5. Publishing Your Own Module

When your module is reusable, you can share it with others!

Structure Example

terraform-aws-mymodule/
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── examples/
└── LICENSE

Steps:

  1. Create & tag version:

     git tag -a v1.0.0 -m "Initial release"
     git push origin v1.0.0
    
  2. Publish on Terraform Registry

  3. Follow naming:
    terraform-<PROVIDER>-<MODULE_NAME> (e.g. terraform-aws-vpc)


🧪 6. Hands-On Lab—Using Multiple Module Sources

Goal: Combine Registry, GitHub, and local modules.

mkdir terraform-module-sources-lab
cd terraform-module-sources-lab

main.tf (abridged):

provider "aws" {
  region = "us-east-1"
  profile = "stackops"
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 6.0"

  name = "stackop-main"
  cidr = "10.0.0.0/16"
}

module "security_group_web" {
  source = "github.com/terraform-aws-modules/terraform-aws-security-group?ref=v5.1.0"
  vpc_id = module.vpc.vpc_id
  name = "stackops-web"
}

Then:

terraform init
terraform plan
terraform apply
terraform destroy

You’ll see modules downloaded in .terraform/modules/.


🔧 7. Module Upgrade Strategy

When new versions are released:

  1. Check for updates

     terraform init -upgrade
     git diff .terraform.lock.hcl
    
  2. Test in dev
    Update the version in yours, apply, and validate.

  3. Review changelog
    Always read release notes for breaking changes.

  4. Gradual rollout:
    Dev → QA → Staging → Production.


📝 Day 19 Summary

Today, you learned how to:

✅ Use Terraform modules from local, Git, S3, and Registry sources
✅ Apply semantic versioning and constraints
✅ Manage module dependencies
✅ Publish your own modules
✅ Upgrade modules safely without breaking production


🚀 Tomorrow’s Preview

Day 20: Remote State & Backend Configuration

Tomorrow we’ll:

  • Configure S3 backend

  • Implement state locking

  • Use remote state data sources

  • Manage multiple state files

  • Implement state isolation strategies


← Day 18: Custom Modules | Day 20: Remote State & Backend →


Remember: Proper versioning ensures stable, predictable infrastructure deployments!

More from this blog

S

StackOps - Diary

33 posts

Welcome to the StackOps - Diary. We’re dedicated to empowering the tech community. We delve into cloud-native and microservices technologies, sharing knowledge to build modern, scalable solutions.