Day 19: Module Sources & Versioning

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
}
| Constraint | Meaning |
= 5.1.2 | Exact version |
>= 5.0.0 | Any version 5.0.0 or newer |
~> 5.0 | \>=5.0, <6.0 |
~> 5.1.0 | \>=5.1.0, <5.2.0 |
!= 5.1.0 | Exclude version 5.1.0 |
✅ Best Practices
Do:
Always pin versions for production
Use
~>for minor auto-updatesDocument module version requirements
Don’t:
Leave version unpinned
Use
latestwithout testingJump to major versions blindly
🌐 3. Using Terraform Registry Modules
The Terraform Registry is like a module marketplace.
Steps:
Go to registry.terraform.io
Search, e.g., “aws vpc.”
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:
Create & tag version:
git tag -a v1.0.0 -m "Initial release" git push origin v1.0.0Publish on Terraform Registry
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:
Check for updates
terraform init -upgrade git diff .terraform.lock.hclTest in dev
Update the version in yours, apply, and validate.Review changelog
Always read release notes for breaking changes.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!


