Skip to content

Commit 86d165d

Browse files
committed
improve gitlab backend configuration
1 parent bef0cea commit 86d165d

File tree

2 files changed

+99
-43
lines changed

2 files changed

+99
-43
lines changed

docs/opentofu-remote-state.md

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,35 @@ deployments.
99
Using remote state is therefore strongly recommended for environments which
1010
should only be instantiated once, e.g. `production` and `staging`.
1111

12-
This page provides some guidance for configuring remote states using
13-
commonly-available backends.
12+
This page provides guidance for configuring remote states using backends
13+
commonly available on OpenStack deployments.
1414

1515
> [!IMPORTANT]
1616
> In the below replace `$ENV` with the relevant environment name.
1717
1818
## GitLab
1919

20-
With the environment activated:
20+
GitLab can be used with the [http backend](https://opentofu.org/docs/language/settings/backends/http/)
21+
to store separate states for each environment within the GitLab project.
22+
Access is protected by GitLab access tokens, which in the approach below are
23+
persisted to local files. Therefore each repository checkout will need to
24+
authenticate separately, using either a separate token or a shared token from
25+
some external secret store.
26+
27+
The below is based on the [official docs](https://docs.gitlab.com/user/infrastructure/iac/terraform_state/)
28+
but includes some missing details and is modified for common appliance workflows.
29+
30+
### Initial setup
2131

22-
1. Create a backend file and commit it:
32+
1. Create the backend file:
33+
34+
```shell
35+
cp environments/site/tofu/example-backends/gitlab.tf environments/$ENV/tofu
36+
```
37+
38+
2. Modify `environments/$ENV/tofu/gitlab.tf` file to set the default for the
39+
project ID. This can be found by clicking the 3-dot menu at the top right of
40+
the GitLab project page.
2341

2442
```terraform
2543
# environments/$ENV/tofu/backend.tf:
@@ -28,63 +46,60 @@ With the environment activated:
2846
}
2947
```
3048

31-
2. Create a personal access token with API access (note Project tokens do not
32-
appear to work):
33-
34-
TODO: appears maybe the do with `project_$ID_bot` as the username
35-
36-
- In GitLab, click on your user button at top left and select 'Preferences'.
37-
- Select 'Access tokens', 'Add new token'.
38-
- Optionally set an expiry date, select 'API' scope and click 'Create token'.
39-
- Copy the generated secret and set an environment variable in your terminal
40-
```shell
41-
export TF_PASSWORD=$SECRET
42-
```
49+
3. Commit it.
4350

44-
TODO: how does this get persisted??
51+
4. Follow the per-checkout steps below.
4552

46-
3. Create this script and commit it:
53+
### Per-checkout configuration
4754

48-
```shell
49-
# environments/$ENV/tofu/init-gitlab-backend.sh
50-
PROJECT_ID="<gitlab-project-id>"
51-
TF_USERNAME="<gitlab-username>"
52-
TF_STATE_NAME="$(basename $APPLIANCES_ENVIRONMENT_ROOT)"
53-
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
54-
55-
tofu init \
56-
-backend-config=address=${TF_ADDRESS} \
57-
-backend-config=lock_address=${TF_ADDRESS}/lock \
58-
-backend-config=unlock_address=${TF_ADDRESS}/lock \
59-
-backend-config=username=${TF_USERNAME} \
60-
-backend-config=password=${TF_PASSWORD} \
61-
-backend-config=lock_method=POST \
62-
-backend-config=unlock_method=DELETE \
63-
-backend-config=retry_wait_min=5
64-
```
55+
1. Create an access token in the GitLab UI, using either:
6556

66-
The project id can be found by clicking the 3-dot menu at the top right of
67-
the GitLab project page.
57+
a. If project access tokens are available, create one via
58+
Project > Settings > Access tokens.
59+
The token must have `Maintainer` role and `api` scope.
60+
61+
b. Otherwise create a personal access token via
62+
User profile > Preferences > Access tokens.
63+
The token must have `api` scope.
64+
65+
Copy the generated secret and set an environment variable:
6866

69-
4. Run the script:
67+
```shell
68+
export TF_VAR_gitlab_access_token=$secret
69+
```
7070

71+
2. If using a personal access token, set the GitLab username as an environment variable:
72+
73+
```shell
74+
export TF_VAR_gitlab_username=$your_username
75+
```
76+
77+
4. With the environment activated, initialise OpenTofu.
78+
79+
If no local state exists run:
80+
7181
```shell
7282
cd environments/$ENV/tofu/
73-
source init-gitlab-backend.sh
83+
tofu init
7484
```
75-
85+
86+
otherwise append `-migrate-state` to the `init` command to attempt to copy
87+
local state to the new backend.
88+
7689
OpenTofu is now configured to use GitLab to store state for this environment.
7790

7891
Repeat for each environment needing remote state.
7992

80-
If the project token expires repeat the above but with the option `-reconfigure`
81-
added to the script.
82-
8393
> [!CAUTION]
8494
> The GitLab credentials are [persisted](https://opentofu.org/docs/language/settings/backends/configuration/#credentials-and-sensitive-data)
8595
> into a file `environments/$ENV/tofu/.terraform/terraform.tfstate` and any
8696
> plan files. These should therefore not be committed.
8797

98+
### Token expiry
99+
100+
If the project token expires repeat the per-checkout configuration, but using
101+
`opentofu init -reconfigure` instead.
102+
88103
## S3
89104

90105
For clouds with S3-compatible object storage (e.g. Ceph with [radosgw](https://docs.ceph.com/en/latest/radosgw/))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
variable "gitlab_username" {
2+
type = string
3+
description = <<-EOF
4+
Username of actual GitLab user, for personal access token only.
5+
Default uses bot account name, for project access token.
6+
EOF
7+
default = null
8+
}
9+
10+
variable "gitlab_access_token" {
11+
type = string
12+
description = <<-EOF
13+
GitLab Project or Personal access token.
14+
Must have Maintainer role (for Project token) and API scope
15+
EOF
16+
}
17+
18+
variable "gitlab_project_id" {
19+
type = string
20+
description = "GitLab project ID - click 3-dot menu at the top right of project page"
21+
default = # Set this here
22+
}
23+
24+
locals {
25+
gitlab_username = coalesce(var.gitlab_username, "project_${var.gitlab_project_id}_bot")
26+
gitlab_state_name = basename(var.environment_root)
27+
gitlab_state_address = "https://gitlab.com/api/v4/projects/${var.gitlab_project_id}/terraform/state/${local.gitlab_state_name}"
28+
}
29+
30+
terraform {
31+
backend "http" {
32+
address = local.gitlab_state_address
33+
lock_address = "${local.gitlab_state_address}/lock"
34+
unlock_address = "${local.gitlab_state_address}/lock"
35+
username = local.gitlab_username
36+
password = var.gitlab_access_token
37+
lock_method = "POST"
38+
unlock_method = "DELETE"
39+
retry_wait_min = 5
40+
}
41+
}

0 commit comments

Comments
 (0)