Module sources, versions and the registry

Terraform · Practical · 8 min

Shared modules save weeks of work, but unpinned ones change underneath you.

The source argument says where a module comes from:

  • Local path: ./modules/vpc (no version; it's your code).
  • Registry: terraform-aws-modules/vpc/aws from the public Terraform Registry, with a version constraint such as ~> 6.0.
  • Git: git::https://github.com/acme/tf-modules.git//network?ref=v1.4.0, where //network is a subdirectory and ref a tag, branch or commit. SSH URLs (git::ssh://git@github.com/...) work too, using your SSH keys.
  • Private registries (HCP Terraform, Terraform Enterprise, Artifactory, GitLab), and archives over HTTP or in S3/GCS buckets.

Version pinning matters: registry modules use the version argument; git sources pin with ref. Tags are convenient but movable; a commit SHA is fully immutable.

Evaluate a public module before adopting it: maintainer, activity, how many inputs it has, and whether its abstractions fit you. The community terraform-aws-modules collection is a common choice for networking and EKS.

terraform init downloads modules into .terraform/modules; after changing a source or version, run terraform init -upgrade (or plain init for a new module).

Publishing your own: a git repo with semver tags (v1.4.0) is enough for git sources; the public registry requires the terraform-<PROVIDER>-<NAME> repository naming.

Example

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

  name            = "main"
  cidr            = "10.0.0.0/16"
  azs             = ["eu-west-1a", "eu-west-1b"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]
}

module "service" {
  # git source, subdirectory //ecs-service, pinned to a tag
  source = "git::https://github.com/acme/tf-modules.git//ecs-service?ref=v1.4.0"
  name   = "shop-api"
  vpc_id = module.vpc.vpc_id
}
# terraform init   -> Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 6.x.y

Remember

  • Registry sources take version; git sources pin with ?ref=
  • // selects a subdirectory in a repo or archive
  • Pin modules as carefully as providers

Watch out for

  • Pointing a git source at a branch like main, so a merge elsewhere changes your next plan.

Check yourself

  1. How do you pin a git-sourced module to release v2.1.0?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.hashicorp.com/terraform/language/modules/sources