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
This configuration has a known issue: when the `destroy` job is not in the same pipeline as the `deploy` job, the `on_stop` environment action does not work.
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).