GitLab Terraform Module Registry: Private Module Hosting and Consumption with CI/CD

The Terraform Module Registry in GitLab provides a private registry for Terraform modules hosted on GitLab projects and groups. With the Terraform Module Registry, you can use GitLab projects as a private registry for Terraform modules. You can create and publish modules with GitLab CI/CD, which can then be consumed from other private projects. The feature is available on Tier Free, Premium, Ultimate and Offering GitLab.com, GitLab Self-Managed, GitLab Dedicated.

The registry unifies infrastructure registry and Terraform Module Registry into a single Terraform Module Registry feature in GitLab 15.11. Support for groups was introduced in GitLab 16.9. Support for Readme files was introduced in GitLab 17.2. Publish Terraform modules in your project’s Infrastructure Registry, then reference them using GitLab as a Terraform module registry was introduced in GitLab 14.0. CI/CD template introduced in GitLab 15.9.

Core capabilities

The Terraform Module Registry allows viewing, authenticating, publishing, referencing, downloading, and deleting Terraform modules. Module resolution works through the Packages API endpoints used by the Terraform CLI.

To view Terraform modules in your project or group:

  • On the left sidebar, select Search or go to and find your project or group.
  • Select Operate > Terraform modules.

You can search, sort, and filter modules on this page. You can also view the module’s Readme file by selecting a module, and then selecting Readme.

Authentication model

To authenticate to the Terraform Module Registry, you need either:

  • A personal access token with at least the read_api scope.
  • A CI/CD job token.
  • A deploy token with the readpackageregistry or writepackageregistry scope, or both.

When using the API:

  • If you authenticate with a deploy token, you must apply the writepackageregistry scope to publish a module. To download a module, apply the readpackageregistry scope.
  • If you authenticate with a personal access token, you must configure it with at least the read_api scope.

Do not use authentication methods other than the methods documented here.

Authentication tokens can be provided for terraform in your ~/.terraformrc file:

credentials "gitlab.com" { token = "<TOKEN>" }

Where gitlab.com can be replaced with the hostname of your self-managed GitLab instance.

For local or temporary environments, you might want to create a ~/.terraformrc or %APPDATA%/terraform.rc file:

credentials "gitlab.com" { token = "<TOKEN>" }

Where gitlab.com can be replaced with the hostname of GitLab Self-Managed.

You can also provide authentication tokens for terraform in your ~/.netrc file:

machine gitlab.com login <USERNAME> password <TOKEN>

Where gitlab.com can be replaced with the hostname of GitLab Self-Managed, and is your token username.

When terraform init runs, it needs to authenticate to your GitLab instance to download private modules.

Environment Variables for CI/CD: Set TFTOKENgitlabcom with a suitable token, replacing gitlabcom with your instance, underscores for dots.

Publishing modules

Publishing Modules Via GitLab CI/CD is recommended.

Structure your module in a dedicated GitLab project. Use a .gitlab-ci.yml file that triggers on Git tags which should follow semantic versioning, e.g., v1.0.1. The CI job will package your module usually as a .tgz archive and use GitLab's API with CIJOBTOKEN to publish it to the registry.

GitLab provides CI/CD templates for this. With templates being deprecated, you might adapt this logic or use newer component-based approaches if available.

CI/CD template introduced in GitLab 15.9.

include:
template: Terraform-Module.gitlab-ci.yml

The pipeline contains the following jobs:

  • fmt
  • Validate the formatting of the Terraform module.
  • kics-iac-sast
  • Test the Terraform module for security issues.
  • deploy
  • For tag pipelines only. Deploy the Terraform module to the GitLab Terraform Registry.

You can configure the pipeline with the following variables:

Variable Default Description
TERRAFORMMODULEDIR ${CIPROJECTDIR} The relative path to the root directory of the Terraform project.
TERRAFORMMODULENAME ${CIPROJECTNAME} The name of your Terraform module. Must not contain any spaces or underscores.
TERRAFORMMODULESYSTEM local The system or provider of your Terraform module targets. For example, local, aws, google.
TERRAFORMMODULEVERSION ${CICOMMITTAG} The Terraform module version

Via API Manually:

You can also use curl and the Packages API with a GitLab Personal Access Token, Project Access Token, or Deploy Token with readpackageregistry and writepackageregistry scopes to upload your packaged module.

Prerequisites for publishing via API:

  • The package name and version must be unique in the top-level namespace.
  • Your project and group names must not include a dot (.). For example, source = "gitlab.example.com/my.group/project.name".
  • You must authenticate with the API. If authenticating with a deploy token, it must be configured with the writepackageregistry scope.
  • The name of a module must be unique within the scope of its group, otherwise an error occurs.

PUT /projects/:id/packages/terraform/modules/:module-name/:module-system/:module-version/file

Attribute Type Required Description
id integer/string yes The ID or URL-encoded path of the project.
module-name string yes The package name. Supported syntax: One to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). The package name can’t exceed 64 characters.
module-system string yes The package system

When you publish a Terraform Module, if it does not exist, it is created.

Referencing and consuming modules

You can then refer to your Terraform Module from a downstream Terraform project:

module "<module>" { source = "gitlab.com/<namespace>/<module-name>/<module-system>" }

Where is the namespace of the Terraform Module Registry.

To reference a Terraform module using a project-level source, use the fetching archives over HTTP source type provided by Terraform.

You can refer to your Terraform module from a downstream Terraform project:

module "<module>" { source = "https://gitlab.com/api/v4/projects/<project-id>/packages/terraform/modules/<module-name>/<module-system>/<module-version>" }

If you need to reference the latest version of a module, you can omit the from the source URL. To prevent future issues, you should reference a specific version if possible.

If there are duplicate module names in the same namespace, referencing the module from the namespace level installs the recently published module.

Example: Referencing a Module from GitLab Registry in your Terraform code:

module "<module>" { source = "gitlab.com/<namespace>/<module-name>/<module-system>" }

Where is the namespace of the Terraform module registry.

API interaction

Terraform Module Registry API

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

Use this API to interact with the Terraform CLI. This API is used by the Terraform CLI and is generally not meant for manual consumption. Undocumented authentication methods might be removed in the future.

List available versions for a specific module

List all available versions for a specified module.

GET packages/terraform/modules/v1/:modulenamespace/:modulename/:module_system/versions

Attribute Type Required Description
module_namespace string yes The top-level group (namespace) to which Terraform module’s project or subgroup belongs.
module_name string yes The module name.
module_system string yes The name of the module system or provider

Module resolution and lifecycle

How module resolution works is documented in the registry.

Disable the Terraform Module Registry can be performed by administrators.

Delete a Terraform module removes a published version.

GitLab has its own private Terraform Registry to host and share your custom modules across your organization.

Conclusion

The GitLab Terraform Module Registry provides a fully integrated path from source to consumption for Terraform modules with authentication enforced through personal access tokens, CI/CD job tokens, and deploy tokens scoped to readpackageregistry and writepackageregistry. Publishing is streamlined through a CI/CD template introduced in GitLab 15.9 with fmt, kics-iac-sast, and deploy jobs, configurable via TERRAFORMMODULEDIR, TERRAFORMMODULENAME, TERRAFORMMODULESYSTEM, and TERRAFORMMODULEVERSION variables. API publishing requires unique package name and version within the top-level namespace, no dots in project and group names, and proper scopes.

Authentication for consumption is supported via ~/.terraformrc credentials blocks or ~/.netrc machine entries, with environment variable TFTOKENgitlab_com for CI/CD. Referencing uses source strings of the form gitlab.com/// or direct HTTP archive URLs via the Packages API. The registry merges infrastructure and module registries in GitLab 15.11, adds group support in 16.9, and Readme viewing in 17.2, while the underlying API remains Terraform CLI driven and not intended for manual consumption.

Sources

  1. https://docs.gitlab.com/user/packages/terraformmoduleregistry/
  2. https://scalr.com/learning-center/using-terraform-with-gitlab
  3. https://docs.gitlab.co.jp/ee/user/packages/terraformmoduleregistry/
  4. https://gitlab-docs-d6a9bb.gitlab.io/ee/user/packages/terraformmoduleregistry/index.html
  5. https://docs.gitlab.com/api/packages/terraform-modules/

Related Posts