Commit c8f5a18e authored by Nicholas Klick's avatar Nicholas Klick

Document Terraform HTTP backend with GitLab API

parent f1a1b4b9
# Infrastructure as Code # Infrastructure as code with GitLab managed Terraform State
GitLab can be used to manage infrastructure as code. The following are some examples: [Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
enable you to store the state file in a remote, shared store. GitLab uses the
[Terraform HTTP backend](https://www.terraform.io/docs/backends/types/http.html)
to securely store the state files in local storage (the default) or
[the remote store of your choice](../../administration/terraform_state.md).
- [A generic tutorial for Terraform with GitLab](https://medium.com/@timhberry/terraform-pipelines-in-gitlab-415b9d842596). The GitLab managed Terraform state backend can store your Terraform state easily and
- [Terraform at GitLab](https://about.gitlab.com/blog/2019/11/12/gitops-part-2/). securely, and spares you from setting up additional remote resources like
Amazon S3 or Google Cloud Storage. Its features include:
- Supporting encryption of the state file both in transit and at rest.
- Locking and unlocking state.
- Remote Terraform plan and apply execution.
To get started, there are two different options when using GitLab managed Terraform State.
- Use a local machine
- Use GitLab CI
## Get Started using local development
If you are planning to only run `terraform plan` and `terraform apply` commands from your local machine, this is a simple way to get started.
First, create your project on your GitLab instance.
Next, define the Terraform backend in your Terraform project to be:
```hcl
terraform {
backend "http" {
}
}
```
Finally, you need to run `terraform init` on your local machine and pass in the following options. The below example is using GitLab.com:
```bash
terraform init \
-backend-config="address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-PROJECT-NAME>" \
-backend-config="lock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-PROJECT-NAME>/lock" \
-backend-config="unlock_address=https://gitlab.com/api/v4/projects/<YOUR-PROJECT-ID>/terraform/state/<YOUR-PROJECT-NAME>/lock" \
-backend-config="username=<YOUR-USERNAME>" \
-backend-config="password=<YOUR-ACCESS-TOKEN>" \
-backend-config="lock_method=POST" \
-backend-config="unlock_method=DELETE" \
-backend-config="retry_wait_min=5"
```
This will initialize your Terraform state and store that state within your GitLab project.
NOTE: YOUR-PROJECT-ID and YOUR-PROJECT-NAME can be accessed from the project main page.
## Get Started using a GitLab CI
Another route is to leverage GitLab CI to run your `terraform plan` and `terraform apply` commands.
### Configure the CI variables
To use the Terraform backend, [first create a Personal Access Token](../profile/personal_access_tokens.md) with the `api` scope. Keep in mind that the Terraform backend is restricted to tokens with [Maintainer access](../permissions.md) to the repository.
To keep the Personal Access Token secure, add it as a [CI/CD environment variable](../../ci/variables/README.md). In this example we set ours to the ENV: `GITLAB_TF_PASSWORD`.
If you are planning to use the ENV on a branch which is not protected, make sure to set the variable protection settings correctly.
### Configure the Terraform backend
Next we need to define the [http backend](https://www.terraform.io/docs/backends/types/http.html). In your Terraform project add the following code block in a `.tf` file such as `backend.tf` or wherever you desire to define the remote backend:
```hcl
terraform {
backend "http" {
}
}
```
### Configure the CI YAML file
Finally, configure a `.gitlab-ci.yaml`, which lives in the root of your project repository.
In our case we are using a pre-built image:
```yaml
image:
name: hashicorp/terraform:light
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
```
We then define some environment variables to make life easier. `GITLAB_TF_ADDRESS` is the URL of the GitLab instance where this pipeline runs, and `TF_ROOT` is the directory where the Terraform commands must be executed.
```yaml
variables:
GITLAB_TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME}
TF_ROOT: ${CI_PROJECT_DIR}/environments/cloudflare/production
cache:
paths:
- .terraform
```
In a `before_script`, pass a `terraform init` call containing configuration parameters.
These parameters correspond to variables required by the
[http backend](https://www.terraform.io/docs/backends/types/http.html):
```yaml
before_script:
- cd ${TF_ROOT}
- terraform --version
- terraform init -backend-config="address=${GITLAB_TF_ADDRESS}" -backend-config="lock_address=${GITLAB_TF_ADDRESS}/lock" -backend-config="unlock_address=${GITLAB_TF_ADDRESS}/lock" -backend-config="username=${GITLAB_USER_LOGIN}" -backend-config="password=${GITLAB_TF_PASSWORD}" -backend-config="lock_method=POST" -backend-config="unlock_method=DELETE" -backend-config="retry_wait_min=5"
stages:
- validate
- build
- test
- deploy
validate:
stage: validate
script:
- terraform validate
plan:
stage: build
script:
- terraform plan
- terraform show
apply:
stage: deploy
environment:
name: production
script:
- terraform apply
dependencies:
- plan
when: manual
only:
- master
```
### Push to GitLab
Pushing your project to GitLab triggers a CI job pipeline, which runs the `terraform init`, `terraform validate`, and `terraform plan` commands automatically.
The output from the above `terraform` commands should be viewable in the job logs.
## Example project
See [this reference project](https://gitlab.com/nicholasklick/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 within a custom VPC.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment