- Authenticate to the Terraform module registry
- Publish a Terraform Module
- Reference a Terraform Module
- Publish a Terraform module by using CI/CD
- Example projects
- Troubleshooting
Terraform module registry
Introduced in GitLab 14.0.
Publish Terraform modules in your project’s Infrastructure Registry, then reference them using GitLab as a Terraform module registry.
Authenticate to the Terraform module registry
To authenticate to the Terraform module registry, you need either:
- A personal access token with at least
read_api
rights. - A CI/CD job token.
Publish a Terraform Module
When you publish a Terraform Module, if it does not exist, it is created.
Prerequisites:
- 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
write_package_registry
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. Supported syntax: One to 64 ASCII characters, including lowercase letters (a-z) and digits (0-9). The package system can’t exceed 64 characters. More information can be found in the Terraform Module Registry Protocol documentation. |
module-version
| string | yes | The package version. It must be valid according to the Semantic Versioning Specification. |
Provide the file content in the request body.
As the following example shows, requests must end with /file
.
If you send a request ending with something else, it results in a 404
error {"error":"404 Not Found"}
.
Example request using a personal access token:
curl --fail-with-body --header "PRIVATE-TOKEN: <your_access_token>" \
--upload-file path/to/file.tgz \
"https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/my-module/my-system/0.0.1/file"
Example response:
{
"message":"201 Created"
}
Example request using a deploy token:
curl --fail-with-body --header "DEPLOY-TOKEN: <deploy_token>" \
--upload-file path/to/file.tgz \
"https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/terraform/modules/my-module/my-system/0.0.1/file"
Example response:
{
"message":"201 Created"
}
Reference a Terraform Module
Prerequisites:
- You need to authenticate with the API. If authenticating with a personal access token, it must be configured with the
read_api
scope.
Authentication tokens (Job Token or Personal Access Token) 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.
You can then refer to your Terraform Module from a downstream Terraform project:
module "<module>" {
source = "gitlab.com/<namespace>/<module-name>/<module-system>"
}
Where <namespace>
is the namespace of the Terraform module registry.
Publish a Terraform module by using CI/CD
CI/CD template introduced in GitLab 15.9.
Use a CI/CD template (recommended)
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 Registry:
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.
Pipeline variables
You can 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 name of your Terraform module. Must not contain any spaces or underscores. |
TERRAFORM_MODULE_SYSTEM
| local
| The system or provider of your Terraform module targets. For example, local , aws , google .
|
TERRAFORM_MODULE_VERSION
| ${CI_COMMIT_TAG}
| The Terraform module version. You should follow the semantic versioning specification. |
Deploy manually via CI/CD
To work with Terraform modules in GitLab CI/CD, you can use
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 Semantic Versioning Specification that Terraform requires. 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, refer to the .gitlab-ci.yml
keyword reference.
Example projects
For examples of the Terraform module registry, check the projects below:
- The GitLab local file project creates a minimal Terraform module and uploads it into the Terraform module registry using GitLab CI/CD.
- The Terraform module test project uses the module from the previous example.
Troubleshooting
- Publishing a module with a duplicate name results in a
{"message":"Access Denied"}
error. There’s an ongoing discussion about allowing duplicate module names in this issue.