Terraform
Terraform
January 16, 2024

Using Gitlab with Terraform

By
Ryan Fee

There are a couple of core components in any infrastructure as code pipelines: An IaC platform, such as Terraform or OpenTofu, and a version control system (VCS) such as Gitlab. Terraform, a widely adopted IaC tool, allows users to define and provision infrastructure using a declarative configuration language. Integrating Terraform with GitLab adds an extra layer of control and collaboration. In this blog, we'll explore all the synergies between Terraform and GitLab and how they can be leveraged to streamline and enhance your infrastructure management workflows.

Gitlab as a VCS Repo

When talking about Terraform and Gitlab, the number one best practice is to make sure your Terraform files are stored in a VCS repository, like Gitlab. By storing the Terraform configuration in a Gitlab project, you enable the following for your infrastructure teams: 

  • Tracking Changes: A VCS keeps track of changes made to Terraform files within a Gitlab project. Each change is associated with a commit, which includes details such as who made the Terraform code changes, when it was made, and a description of the modifications.
  • Collaboration: VCS enables multiple developers to work on the same Gitlab project simultaneously. Each developer can make changes independently, and the VCS helps merge these changes seamlessly, preventing conflicts and ensuring a coherent Terraform codebase.
  • History and Rollback: VCS maintains a complete history of all changes made to the Terraform code. This allows developers to roll back to previous versions of the Terraform code in case of errors or to investigate when a specific change was introduced.
  • Branching and Merging: VCS allows developers to create branches, which are independent lines of Terraform code development. This feature is valuable for working on new features, bug fixes, or experimental changes without affecting the main Terraform codebase. By opening a merge request, you have the ability to automatically trigger a “Terraform dry run” in tools like Scalr or Terraform Cloud, which will execute a Terraform plan and send the results back into Gitlab. Based on the results coming back successfully, developers can then merge the code allowing changes from one branch to be incorporated into another.
  • Code Review: VCS facilitates Terraform code reviews by providing a clear view of the changes made in a commit. Reviewers can easily assess the modifications, leave comments, and suggest improvements before changes are merged into the main branch.

Using Gitlab with a TACO (Terraform Collaboration and Automation Platform)

If you are looking for a TACO, such as Scalr or Terraform Cloud, to help scale your Terraform operations, the integration with Gitlab is a key feature. By integrating these tools with Gitlab, you are not only able to pull in the Terraform code, but also enable the following features:

  • Terraform Private Module Registry: On top of storing your Terraform code in Gitlab for the reasons stated above, another best practice is to implement at Terraform Private Module Registry to store your Terraform modules. When doing this, you store your Terraform modules in Gitlab projects, integrate Scalr or Terraform Cloud with Gitlab and then pull the Terraform modules in for use by your DevOps teams. By doing this, Gitlab is still the source of truth for the code, but you can now curate a list of approved modules for your teams to use.
  • GitOps Workflow: A GitOps workflow for Terraform is usually the goal for most DevOps teams. A GitOps workflow can leverage the Gitlab branching and merging to automatically kick off Terraform dry runs as well as Terraform applies. The flow is typically as follows:
    1. A branch, let’s call it dev, is created based off the main branch.
    2. Terraform code is updated in the dev branch.
    3. A merge request is opened up against the main branch from dev.
    4. Based on the merge request being opened, the TACO will automatically execute a Terraform dry run and send the results back to Gitlab.
    5. Admins can optionally (considered a best practice though) set branch policies to only allow a merge request if all checks come back successfully from the TACO.
    6. Once the merge request is approved the Terraform apply will execute in the TACO.
  • Open Policy Agent: Open Policy Agent (OPA) with Terraform enables declarative policy enforcement for the Terraform code, allowing admins to define and enforce fine-grained policies to govern the provisioning workflow. Typically, the OPA policies are stored in Gitlab and then pulled into Scalr or Terraform Cloud to enforce it in the core workflow.

The TACO products have a full feature set dedicated to Terraform, including the ability to store terraform state files. See more here.

Gitlab CI with Terraform

If you want to use a more traditional CI/ CD pipeline, rather than a purpose-built product like Scalr for your Terraform deployments, then Gitlab CI might be an option. GitLab CI/CD allows you to define and manage pipelines, which are automated workflows that specify the steps to be executed for building, testing, and deploying your Terraform code.

Gitlab pipelines are configured using a .gitlab-ci.yml file, written in YAML, where you define jobs, stages, and scripts for each step of the CI/CD process. Here is a very basic example of the YAML file where you will see the Terraform commands being executed:

stages:
  - plan
  - apply

plan:
  script:
    - terraform init
    - terraform plan -out=tfplan

apply:
  script:
  - terraform init
  - terraform apply -auto-approve
  only:
    - master

See more in the official Gitlab documentation here. Gitlab also provides a mechanism for storing Terraform state files.

Using The Gitlab Terraform Provider

In this last use case, we are turning things around a little. Instead of Gitlab assisting in managing Terraform, we are using the Gitlab Terraform provider to actually manage Gitlab. Just like you would use Terraform to manage AWS resources, the same can be done to manage Gitlab resources. Here are a couple of examples:

Creating a Gitlab project:

resource "gitlab_project" "example" {
      name        = "Terraform Module"
      description = "My new Terraform project"

      visibility_level = "public"
 }

Creating a Gitlab Branch:

# Create a project first, then a branch
 resource "gitlab_project" "example" {
      name         = "Terraform Module"
      description  = "My new Terraform project"
      namespace_id = gitlab_group.example.id
  }

 resource "gitlab_branch" "example" {
      name    = "example"
      ref     = "feature"
      project = gitlab_project.example.id
  }

Using the Gitlab provider is a great best practice to get started with early on, even if you don’t have many projects. As you scale your usage, you can create a vending machine using Terraform modules to automatically create Github projects as new apps are created.

Summary

As you can see, integrating Gitlab into your infrastructure as code pipeline provides many different advantages ranging from just using the Terraform provider, to using it as a code repository, or integrating it with a product like Scalr or Terraform Cloud. Gitlab isn’t the only product that can do this, be sure to check out similar features in Github, Bitbucket, or Azure DevOps.

Start using the Terraform platform of the future.

A screenshot of the modules page in the Scalr Platform