GitLab CI Configuration
The gitlab section configures the generated GitLab CI pipeline.
Options
terraform_binary
Type: stringDefault: "terraform"
The Terraform/OpenTofu binary to use.
gitlab:
terraform_binary: "terraform" # or "tofu"This sets the TERRAFORM_BINARY variable in the pipeline.
image
Type: string or objectDefault: "hashicorp/terraform:1.6"Required: Yes
Docker image for Terraform jobs (in default section). Supports both simple string format and object format with entrypoint override.
String format (simple):
gitlab:
# Terraform
image: "hashicorp/terraform:1.6"
# OpenTofu
image: "ghcr.io/opentofu/opentofu:1.6"
# Custom image
image: "registry.example.com/terraform:1.6"Object format (with entrypoint):
gitlab:
# OpenTofu minimal image requires entrypoint override
image:
name: "ghcr.io/opentofu/opentofu:1.9-minimal"
entrypoint: [""]
# Custom image with specific entrypoint
image:
name: "registry.example.com/terraform:1.6"
entrypoint: ["/bin/sh", "-c"]OpenTofu Minimal Images
OpenTofu minimal images (e.g., opentofu:1.9-minimal) have a non-shell entrypoint. Use the object format with entrypoint: [""] to override it for GitLab CI compatibility.
Deprecation Notice
The terraform_image field is deprecated. Use image instead.
stages_prefix
Type: stringDefault: "deploy"
Prefix for generated stage names.
gitlab:
stages_prefix: "deploy" # Produces: deploy-plan-0, deploy-apply-0
# stages_prefix: "terraform" # Produces: terraform-plan-0, terraform-apply-0parallelism
Type: integerDefault: 5
Maximum number of parallel jobs per stage (reserved for future use).
gitlab:
parallelism: 5plan_enabled
Type: booleanDefault: true
Generate separate plan jobs.
gitlab:
plan_enabled: true # plan + apply jobs
# plan_enabled: false # apply onlyWhen enabled, generates:
plan-*jobs that runterraform planapply-*jobs that apply the saved plan
When disabled, generates only apply-* jobs that run terraform apply.
auto_approve
Type: booleanDefault: false
Auto-approve apply jobs without manual trigger.
gitlab:
auto_approve: false # Apply requires manual trigger (when: manual)
# auto_approve: true # Apply runs automaticallycache_enabled
Type: booleanDefault: false
Enable caching of .terraform directory for each module. This significantly speeds up pipeline execution by reusing downloaded providers and modules.
gitlab:
cache_enabled: trueWhen enabled, each job will have a cache configuration:
plan-platform-prod-vpc:
cache:
key: platform-prod-us-east-1-vpc
paths:
- platform/prod/us-east-1/vpc/.terraform/The cache key is derived from the module path with slashes replaced by dashes.
init_enabled
Type: booleanDefault: true
Automatically run terraform init after changing to the module directory. This ensures initialization happens in the correct context.
gitlab:
init_enabled: true # Adds ${TERRAFORM_BINARY} init after cd
# init_enabled: false # Skip automatic init (use job_defaults.before_script instead)The generated script will be:
script:
- cd platform/prod/us-east-1/vpc # Change to module directory
- ${TERRAFORM_BINARY} init # Auto-added when init_enabled: true
- ${TERRAFORM_BINARY} plan -out=... # Main commandvariables
Type: map[string]stringDefault: {}
Global pipeline variables.
gitlab:
variables:
TF_IN_AUTOMATION: "true"
TF_INPUT: "false"
AWS_DEFAULT_REGION: "us-east-1"rules
Type: arrayDefault: []
Workflow rules for conditional pipeline execution. Controls when pipelines are created.
gitlab:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- if: '$CI_COMMIT_TAG'
when: never
- when: neverGenerated output:
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- when: neverEach rule can have:
if- Condition expressionwhen- When to run:always,never,on_success,manual,delayedchanges- File patterns that trigger the rule
job_defaults
Type: objectDefault: null
Default settings applied to all generated jobs (both plan and apply). These are applied before overwrites, so overwrites can override job_defaults.
Available fields:
image- Docker image for all jobsid_tokens- OIDC tokens for all jobssecrets- Secrets for all jobsbefore_script- Commands before each jobafter_script- Commands after each jobartifacts- Artifacts configurationtags- Runner tagsrules- Job-level rulesvariables- Additional variables
Example: Common settings for all jobs
gitlab:
job_defaults:
tags:
- terraform
- docker
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
variables:
CUSTOM_VAR: "value"overwrites
Type: arrayDefault: []
Job-level overrides for plan or apply jobs. Allows customizing specific job types with different settings. Applied after job_defaults.
Each overwrite has:
type- Which jobs to override:planorapplyimage- Override Docker imageid_tokens- Override OIDC tokenssecrets- Override secretsbefore_script- Override before_scriptafter_script- Override after_scriptartifacts- Override artifacts configurationtags- Override runner tagsrules- Set job-level rulesvariables- Override/add variables
Example: Different images for plan and apply
gitlab:
image: "hashicorp/terraform:1.6"
overwrites:
- type: plan
image: "custom/terraform-plan:1.6"
tags:
- plan-runner
- type: apply
image: "custom/terraform-apply:1.6"
tags:
- apply-runner
- productionExample: Add job-level rules for apply jobs
gitlab:
overwrites:
- type: apply
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
- when: neverExample: Different secrets for different job types
gitlab:
job_defaults:
secrets:
COMMON_SECRET:
vault: common/secret@namespace
overwrites:
- type: apply
secrets:
DEPLOY_KEY:
vault: deploy/key@namespace
file: trueExample: job_defaults with overwrites
gitlab:
# Common settings for all jobs
job_defaults:
tags:
- terraform
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_success
# Override for apply jobs only
overwrites:
- type: apply
tags:
- terraform
- production
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manualFull Example
gitlab:
# Binary configuration
terraform_binary: "terraform"
image: "hashicorp/terraform:1.6"
# Pipeline structure
stages_prefix: "deploy"
parallelism: 5
plan_enabled: true
auto_approve: false
cache_enabled: true
init_enabled: true
# Pipeline variables
variables:
TF_IN_AUTOMATION: "true"
TF_INPUT: "false"
# Workflow rules
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# Job defaults (applied to all jobs)
job_defaults:
tags:
- terraform
- docker
before_script:
- aws sts get-caller-identity
after_script:
- echo "Job completed"
id_tokens:
AWS_OIDC_TOKEN:
aud: "https://gitlab.example.com"
secrets:
CREDENTIALS:
vault: ci/terraform/credentials@namespace
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_success
# Job overwrites (override job_defaults for specific job types)
overwrites:
- type: apply
tags:
- production
- secure
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manualGenerated Output
With the above configuration, TerraCi generates:
variables:
TERRAFORM_BINARY: "terraform"
TF_IN_AUTOMATION: "true"
TF_INPUT: "false"
default:
image: hashicorp/terraform:1.6
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
stages:
- deploy-plan-0
- deploy-apply-0
plan-platform-prod-vpc:
stage: deploy-plan-0
script:
- cd platform/prod/us-east-1/vpc
- ${TERRAFORM_BINARY} init
- ${TERRAFORM_BINARY} plan -out=plan.tfplan
variables:
TF_MODULE: vpc
# ...
tags:
- terraform
- docker
before_script:
- aws sts get-caller-identity
after_script:
- echo "Job completed"
id_tokens:
AWS_OIDC_TOKEN:
aud: "https://gitlab.example.com"
secrets:
CREDENTIALS:
vault: ci/terraform/credentials@namespace
artifacts:
paths:
- platform/prod/us-east-1/vpc/plan.tfplan
expire_in: 1 day
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_success
cache:
key: platform-prod-us-east-1-vpc
paths:
- platform/prod/us-east-1/vpc/.terraform/
apply-platform-prod-vpc:
stage: deploy-apply-0
script:
- cd platform/prod/us-east-1/vpc
- ${TERRAFORM_BINARY} init
- ${TERRAFORM_BINARY} apply plan.tfplan
needs:
- plan-platform-prod-vpc
tags:
- production
- secure
before_script:
- aws sts get-caller-identity
after_script:
- echo "Job completed"
id_tokens:
AWS_OIDC_TOKEN:
aud: "https://gitlab.example.com"
secrets:
CREDENTIALS:
vault: ci/terraform/credentials@namespace
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manualPer-Job Variables
Each job receives these variables:
| Variable | Description | Example |
|---|---|---|
TF_MODULE_PATH | Relative path to module | platform/prod/us-east-1/vpc |
TF_SERVICE | Service name | platform |
TF_ENVIRONMENT | Environment name | prod |
TF_REGION | Region name | us-east-1 |
TF_MODULE | Module name | vpc |