info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Terraform template recipes **(FREE)**
You can customize your Terraform integration by adding the recipes on
this page to your pipeline.
If you'd like to share your own Terraform configuration, consider
[contributing a recipe](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/infrastructure/iac/terraform_template_recipes.md)
to this page.
## Enable a `terraform destroy` job
Add the following snippet to your `.gitlab-ci.yml`:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
destroy:
extends: .terraform:destroy
```
The `destroy` job is part of the `cleanup` stage. Like the `deploy`
job, the `destroy` job is always `manual` and is not tied to the
default branch.
## Run a custom `terraform` command in a job
To define a job that runs a custom `terraform` command, the
`gitlab-terraform` wrapper can be used in any job:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
state-list:
stage: validate # you can use any stage, just make sure to define it
script: gitlab-terraform state list
```
The `gitlab-terraform` command sets up a `terraform` command and runs
it with the given arguments.
To run this job in the Terraform state-specific [resource group](../../../ci/resource_groups/index.md),
assign the job with `resource_group`:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
state-list:
stage: validate # you can use any stage, just make sure to define it
resource_group: ${TF_STATE_NAME}
script: gitlab-terraform state list
```
## Add custom debug tools to jobs
The default image used by Terraform template jobs contains only minimal tooling.
However, you might want to add additional tools for debugging.
To add an additional tool:
1. Install the tool in the `before_script` of a job or pipeline.
1. Use the tool in the `script` or `after_script` block.
- If you use the `script` block, be sure to re-add the template job commands.
For example, the following snippet installs `bash` and `jq` in the `before_script` for all
jobs in the pipeline:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
default:
before_script: apk add --update bash jq
```
To add it to only the `build` and `deploy` jobs, add it to those jobs directly:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
build:
before_script: apk add --update bash jq
deploy:
before_script: apk add --update bash jq
```
## Add custom container images
For debug tools and simple installations, you should
[add a custom debug tool to your job](#add-custom-debug-tools-to-jobs).
If your tool is complex or benefits from caching,
you can create a custom container image based on the
You can use your custom image in subsequent Terraform jobs.
To define a custom container image:
1. Define a new `Dockerfile` with custom tooling. For example, install `bash` and `jq` in `.gitlab/ci/Dockerfile`:
```dockerfile
FROM registry.gitlab.com/gitlab-org/terraform-images/stable:latest
RUN apk add --update bash jq
```
1. In a new job, define a `prepare` stage that builds the image whenever the `Dockerfile` changes.
- The built image is pushed to the [GitLab Container Registry](../../packages/container_registry). A tag is applied to indicate whether the image was built from a merge request or from the default branch.
1. Use your image in your Terraform jobs, such as `build` and `deploy`.
- You can combine your image with specialized `before_script` configurations to perform setup commands, like to generate inputs for Terraform.
For example, a fully functioning pipeline configuration might look like:
```yaml
include:
- template: Terraform.latest.gitlab-ci.yml
variables:
IMAGE_TAG: latest
workflow:
rules:
- if: $CI_MERGE_REQUEST_IID
changes:
- .gitlab/ci/Dockerfile
variables:
IMAGE_TAG: ${CI_COMMIT_REF_SLUG}
- when: always
stages:
- prepare
- validate
- test
- build
- deploy
- cleanup
prepare:image:
needs: []
stage: prepare
image:
name: gcr.io/kaniko-project/executor:v1.9.0-debug
entrypoint: [""]
rules:
# Tag with the commit SHA if we're in an MR
- if: $CI_MERGE_REQUEST_IID
changes:
- .gitlab/ci/Dockerfile
variables:
DOCKER_TAG: $CI_COMMIT_REF_SLUG
# If we're on our main branch, tag with "latest"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
changes:
- .gitlab/ci/Dockerfile
variables:
DOCKER_TAG: latest
before_script:
# Authenticate to the docker registry and dependency proxy
For an example repository, see the [GitLab Terraform template usage project](https://gitlab.com/gitlab-org/configure/examples/terraform-template-usage).
This configuration is modified from the [base GitLab template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml).