doc/user/packages/terraform_module_registry/_index.md
{{< details >}}
{{< /details >}}
{{< history >}}
{{< /history >}}
With the Terraform Module Registry, you can:
To authenticate to the Terraform Module Registry, you need either:
read_api scope.read_package_registry or write_package_registry scope, or both.When using the API:
write_package_registry scope to publish a module. To download a module, apply the read_package_registry scope.read_api scope.Do not use authentication methods other than the methods documented here. Undocumented authentication methods might be removed in the future.
To publish a Terraform module:
To delete a module:
Publishing a Terraform module creates it if it does not exist.
After you publish a Terraform module, you can view it in the Terraform Module Registry page.
Publish Terraform modules by using the Terraform Module Registry API.
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 module name. Supported syntax: 1 to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). |
module-system | string | yes | The module system. Supported syntax: 1 to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). For more information, see Module Registry Protocol. |
module-version | string | yes | The module version. Should follow the semantic versioning specification. |
Provide the file content in the request body.
Requests must end with /file.
If you send a request ending with something else, it results in a 404 Not Found error.
{{< tabs >}}
{{< tab title="Personal access token" >}}
Example request using a personal access token:
curl --fail-with-body --header "PRIVATE-TOKEN: <your_access_token>" \
--upload-file path/to/file.tgz \
--url "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/<your_module>/<your_system>/0.0.1/file"
{{< /tab >}}
{{< tab title="Deploy token" >}}
Example request using a deploy token:
curl --fail-with-body --header "DEPLOY-TOKEN: <deploy_token>" \
--upload-file path/to/file.tgz \
--url "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/<your_module>/<your_system>/0.0.1/file"
{{< /tab >}}
{{< /tabs >}}
Example response:
{
"message":"201 Created"
}
{{< history >}}
{{< /history >}}
You can use the Terraform-Module.gitlab-ci.yml
or the advanced Terraform/Module-Base.gitlab-ci.yml
CI/CD template to publish a Terraform module to the GitLab Terraform Module Registry:
include:
template: Terraform-Module.gitlab-ci.yml
The pipeline contains the following jobs:
fmt: Validates the formatting of the Terraform modulekics-iac-sast: Tests the Terraform module for security issuesdeploy: Deploys the Terraform module to the Terraform Module Registry (for tag pipelines only)Configure the pipeline with the following variables:
| Variable | Default | Description |
|---|---|---|
TERRAFORM_MODULE_DIR | ${CI_PROJECT_DIR} | The relative path to the root directory of the Terraform project. |
TERRAFORM_MODULE_NAME | ${CI_PROJECT_NAME} | The module name. Must not contain any spaces or underscores. |
TERRAFORM_MODULE_SYSTEM | local | The system or provider of your module targets. For example, local, aws, or google. |
TERRAFORM_MODULE_VERSION | ${CI_COMMIT_TAG} | The module version. Should follow the semantic versioning specification. |
To work with Terraform modules in GitLab CI/CD, use a
CI_JOB_TOKEN in place of the personal access token in your commands.
For example, this job uploads a new module for the local system provider
and uses the module version from the Git commit tag:
stages:
- deploy
upload:
stage: deploy
image: curlimages/curl:latest
variables:
TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR} # The relative path to the root directory of the Terraform project.
TERRAFORM_MODULE_NAME: ${CI_PROJECT_NAME} # The name of your Terraform module, must not have any spaces or underscores (will be translated to hyphens).
TERRAFORM_MODULE_SYSTEM: local # The system or provider your Terraform module targets (ex. local, aws, google).
TERRAFORM_MODULE_VERSION: ${CI_COMMIT_TAG} # The version - it's recommended to follow SemVer for Terraform Module Versioning.
script:
- TERRAFORM_MODULE_NAME=$(echo "${TERRAFORM_MODULE_NAME}" | tr " _" -) # module-name must not have spaces or underscores, so translate them to hyphens
- tar -vczf /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz -C ${TERRAFORM_MODULE_DIR} --exclude=./.git .
- 'curl --fail-with-body --location --header "JOB-TOKEN: ${CI_JOB_TOKEN}"
--upload-file /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz
${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/terraform/modules/${TERRAFORM_MODULE_NAME}/${TERRAFORM_MODULE_SYSTEM}/${TERRAFORM_MODULE_VERSION}/file'
rules:
- if: $CI_COMMIT_TAG
To trigger this upload job, add a Git tag to your commit.
Ensure the tag follows the required semantic versioning specification for Terraform.
The rules:if: $CI_COMMIT_TAG ensures
that only tagged commits to your repository trigger the module upload job.
For other ways to control jobs in your CI/CD pipeline, see the CI/CD YAML syntax reference.
When you upload a new module, GitLab generates a path for the module. For example:
https://gitlab.example.com/parent-group/my-infra-packageThis path conforms with the Terraform Module Registry Protocol, where:
gitlab.example.com is the hostname.parent-group is the unique, top-level namespace of the Terraform Module Registry.my-infra-package is the name of the module.If duplicates are not allowed, the module name and version must be unique in all groups, subgroups, and projects under parent-group. Otherwise, you receive the following error:
{"message":"A module with the same name already exists in the namespace."}If duplicates are allowed, module resolution is based on the most recently published module.
For example, if:
gitlab.example.com/parent-group/subgroup/my-project.my-infra-package.If duplicates are allowed, my-infra-package is a valid module.
If duplicates are not allowed, the module name must be unique in all
projects in all groups under parent-group.
When you name a module, keep these naming conventions in mind:
.).
For example, source = "gitlab.example.com/my.group/project.name" is invalid.{{< history >}}
{{< /history >}}
By default, the Terraform Module Registry enforces uniqueness for module names in the same namespace.
To allow publishing duplicate module names:
Your changes are automatically saved.
[!note] If Allow duplicates is turned on, you can specify module names that should not have duplicates in the Exceptions text box.
You can also allow publishing duplicate names by enabling terraform_module_duplicates_allowed in the GraphQL API.
To allow duplicates with specific names:
terraform_module_duplicates_allowed is disabled.terraform_module_duplicate_exception_regex to define a regex pattern for the module names you want to allow duplicates for.The top-level namespace setting takes precedence over the child namespace settings.
For example, if you enable terraform_module_duplicates_allowed for a group, and disable it for a subgroup,
duplicates are allowed for all projects in the group and its subgroups.
For more information on module resolution, see module resolution workflow
{{< history >}}
README files introduced in GitLab 17.2.{{< /history >}}
To view Terraform modules in your project or group:
You can search, sort, and filter modules on this page.
To view a module's README file:
README.Reference a module from a group or project.
You can provide authentication tokens (job tokens, personal access tokens, or deploy tokens) for terraform in environment variables.
You should add the prefix TF_TOKEN_ to the domain name of environment variables, with periods encoded as underscores.
For more information, see Environment Variable Credentials.
For example, the value of a variable named TF_TOKEN_gitlab_com is used as a deploy token when the CLI makes service requests to the hostname gitlab.com:
export TF_TOKEN_gitlab_com='glpat-<deploy_token>'
This method is preferred for enterprise implementations. 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
your GitLab Self-Managed instance.
You can then refer to your Terraform module from a downstream Terraform project:
module "<module>" {
source = "gitlab.com/<namespace>/<module-name>/<module-system>"
}
To reference a Terraform module using a project source, use the fetching archives over HTTP source type provided by Terraform.
You can provide authentication tokens (job tokens, personal access tokens, or deploy tokens) for terraform in your ~/.netrc file:
machine <gitlab.com>
login <USERNAME>
password <TOKEN>
Where gitlab.com can be replaced with the hostname of your GitLab Self-Managed instance,
and <USERNAME> is your token username.
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 <module-version> 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. To reference a specific version of a duplicate module, use the project-level source type.
To download a Terraform module:
You cannot edit a Terraform module after you publish it in the Terraform Module Registry. Instead, you must delete and recreate it.
You can delete modules by using the packages API or the UI.
To delete a module in the UI, from your project:
The package is permanently deleted.
The Terraform Module Registry is automatically enabled.
For GitLab Self-Managed instances, a GitLab administrator can disable Packages and registries, which removes this menu item from the sidebar.
You can also remove the Terraform Module Registry for a specific project:
For examples of the Terraform Module Registry, check the projects below: