How to Manage GitLab with Terraform

The guide covers using the Terraform provider for GitLab to configure, authenticate, create core resources like groups & projects, and use the Terraform state backend and module registry.

Introduction

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.

Why Manage GitLab with Terraform?

Managing GitLab as code helps with:

  • Standardization: Codify repository settings, group structures, and permissions to ensure consistent configuration across all projects and prevent drift.
  • Version Control & Auditing: Treat platform configuration as code, providing a complete, versioned history of all changes for auditing purposes.
  • Security: Define and enforce security policies like branch protection rules programmatically across all projects, ensuring a consistent security posture.
  • Automation & Efficiency: Automate the provisioning of projects and management of user access, reducing manual effort and accelerating project setup.

Provider Configuration and Authentication

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.

  1. Navigate to your GitLab Preferences > Access Tokens.
  2. Assign a name, set an optional expiration, and grant the api and read_api scopes.
  3. Copy the generated token.

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.

Resource Management Examples

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.
}
  1. Execution and Deployment After defining the resources, use the standard Terraform workflow to deploy the changes.
  2. Review the Execution Plan: terraform plan
  3. Apply the Configuration: terraform apply

Leveraging GitLab for Terraform

GitLab 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.

  • Configuration: Add the backend "http" block to your providers.tf.
  • Authentication in CI/CD: The backend seamlessly authenticates within GitLab CI/CD pipelines using the predefined 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.

  • Branch Protection: Use the gitlab_branch_protection resource to codify rules for your branches, such as requiring merge request approvals.
  • CI/CD Integration: Build a full CI/CD pipeline in GitLab to automate the plan and apply cycle, using merge requests for review.
  • Secrets Management: Manage sensitive data like API keys using GitLab's protected and masked CI/CD variables.