
This guide provides a technical overview and practical instructions for managing GitLab resources using Terraform. By leveraging the gitlabhq/gitlab provider, organizations can adopt an Infrastructure as Code (IaC) approach to define, version, and automate the configuration of their GitLab environment. This method ensures consistency, enforces security policies at scale, and provides an auditable history of all changes.
Managing GitLab as code helps with:
The initial step is to configure Terraform to communicate with the GitLab API. Authentication is handled via access tokens, which should be managed securely.
1. Generate an Access Token For local development, a Personal Access Token (PAT) is the most direct method.
api and read_api scopes.For production automation, using the predefined CI_JOB_TOKEN within GitLab CI/CD is the recommended and most secure practice.
2. Set Environment Variables Configure the access token in your terminal session. The Terraform provider will automatically detect and use this variable.
export GITLAB_TOKEN="your_gitlab_token_here"3. Define Provider Configuration Create a file named providers.tf to declare the GitLab provider and its configuration.
// providers.tf
terraform {
required_providers {
gitlab = {
source = "gitlabhq/gitlab"
version = "~> 18.1"
}
}
}
// Configure the GitLab provider.
// Authentication is handled by the GITLAB_TOKEN environment variable.
provider "gitlab" {
// For self-hosted instances, specify the API base URL.
// base_url = "https://gitlab.example.com/api/v4/"
}After creating this file, run terraform init to download and initialize the provider.
The following sections demonstrate how to define core GitLab resources.
1. Managing Groups and Subgroups In GitLab, Groups are used to organize projects and manage user access. On GitLab.com, top-level groups must be created in the UI first and then referenced via a data source.
// gitlab.tf
// Use a data source to reference an existing top-level group.
data "gitlab_group" "parent_group" {
full_path = "your-existing-top-level-group" // Specify the full path of the parent group.
}
// Define a new subgroup for the project team.
resource "gitlab_group" "app_subgroup" {
name = "My Terraform App Team"
path = "my-terraform-app-team"
parent_id = data.gitlab_group.parent_group.id
visibility_level = "private"
}2. Managing Projects Projects (the equivalent of repositories) are created within a group's namespace.
// gitlab.tf
resource "gitlab_project" "app_project" {
name = "My First TF Project"
namespace_id = gitlab_group.app_subgroup.id
description = "Project created via Terraform."
visibility_level = "private"
}3. Managing Users and Group Membership You can assign existing users to groups with specific access levels.
// gitlab.tf
// Use a data source to find a user by username.
data "gitlab_user" "a_user" {
username = "a-real-gitlab-username" // Specify a valid GitLab username.
}
// Add the user to the subgroup with "Developer" access.
resource "gitlab_group_membership" "user_membership" {
group_id = gitlab_group.app_subgroup.id
user_id = data.gitlab_user.a_user.id
access_level = "developer" // Valid levels: guest, reporter, developer, maintainer, owner.
}terraform planterraform applyGitLab provides native support for Terraform too.

1. The GitLab-Managed Terraform State Backend GitLab offers a built-in HTTP backend to securely store and lock your Terraform state file. This is critical for team collaboration.
backend "http" block to your providers.tf.CI_JOB_TOKEN, eliminating the need to manage credentials manually.Example CI/CD Initialization:
# In .gitlab-ci.yml
variables:
TF_STATE_NAME: "default"
TF_ADDRESS: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
before_script:
- terraform init -reconfigure \
-backend-config="address=${TF_ADDRESS}" \
-backend-config="lock_address=${TF_ADDRESS}/lock" \
-backend-config="unlock_address=${TF_ADDRESS}/lock" \
-backend-config="username=gitlab-ci-token" \
-backend-config="password=${CI_JOB_TOKEN}" \
-backend-config="lock_method=POST" \
-backend-config="unlock_method=DELETE"2. The Private GitLab Terraform Module Registry You can publish, version, and share your own Terraform modules privately within your GitLab instance. This promotes code reuse and standardization. Modules are published via a CI/CD pipeline and can be consumed in other projects by referencing the module's GitLab URL.
Read more on how GitLab can help your team use Terraform.
gitlab_branch_protection resource to codify rules for your branches, such as requiring merge request approvals.plan and apply cycle, using merge requests for review.