1
1
# OpenTofu remote state
2
2
3
- Generally, using [ remote state] ( https://opentofu.org/docs/language/state/remote/ )
4
- is recommended.
3
+ OpenTofu supports a number of [ remote state backends] ( https://opentofu.org/docs/language/state/remote/ )
4
+ which can be used to persist state independently of where a deployment is run.
5
+ This allows deployments to be made from anywhere that can access the state
6
+ without corrupting or conflicting with any existing resources from previous
7
+ deployments.
5
8
6
- This can be configured by adding additional files into the
7
- ` environments/{production,staging,...}/tofu ` directories. Some guidance for
8
- different backends is given here.
9
+ Using remote state is therefore strongly recommended for environments which
10
+ should only be instantiated once, e.g. ` production ` and ` staging ` .
9
11
12
+ This page provides some guidance for configuring remote states using
13
+ commonly-available backends.
14
+
15
+ > [ !IMPORTANT]
16
+ > In the below replace ` $ENV ` with the relevant environment name.
10
17
11
18
## GitLab
12
19
13
- The following creates a state per environment.
20
+ With the environment activated:
14
21
15
22
1 . Create a backend file and commit it:
16
23
17
24
``` terraform
18
25
# environments/$ENV/tofu/backend.tf:
19
26
terraform {
20
- backend "http" {}
27
+ backend "http" {}
21
28
}
22
29
```
23
30
24
31
2. Create a personal access token with API access (note Project tokens do not
25
32
appear to work):
33
+
34
+ TODO: appears maybe the do with `project_$ID_bot` as the username
35
+
26
36
- In GitLab, click on your user button at top left and select 'Preferences'.
27
37
- Select 'Access tokens', 'Add new token'.
28
38
- Optionally set an expiry date, select 'API' scope and click 'Create token'.
29
- - Copy the generated secret and set an environment variable in your terminal:
30
-
39
+ - Copy the generated secret and set an environment variable in your terminal
31
40
```shell
32
41
export TF_PASSWORD=$SECRET
33
42
```
34
43
44
+ TODO: how does this get persisted??
45
+
35
46
3. Create this script and commit it:
36
- it:
37
47
38
48
```shell
39
49
# environments/$ENV/tofu/init-gitlab-backend.sh
@@ -56,21 +66,102 @@ The following creates a state per environment.
56
66
The project id can be found by clicking the 3-dot menu at the top right of
57
67
the GitLab project page.
58
68
59
- 4. With the environment activated, run the script:
69
+ 4. Run the script:
60
70
61
71
```shell
62
72
cd environments/$ENV/tofu/
63
73
source init-gitlab-backend.sh
64
74
```
65
75
66
- OpenTofu is now configured to use GitLab to store state for this environment.
76
+ OpenTofu is now configured to use GitLab to store state for this environment.
67
77
68
- Repeat for each environment needing remote state. Generally, `dev` environments
69
- will be personal so should not need this.
78
+ Repeat for each environment needing remote state.
70
79
71
- If the project token expires, follow the above again by add an option `-reconfigure`
72
- to the script.
80
+ If the project token expires repeat the above but with the option `-reconfigure`
81
+ added to the script.
82
+
83
+ > [!CAUTION]
84
+ > The GitLab credentials are [persisted](https://opentofu.org/docs/language/settings/backends/configuration/#credentials-and-sensitive-data)
85
+ > into a file `environments/$ENV/tofu/.terraform/terraform.tfstate` and any
86
+ > plan files. These should therefore not be committed.
73
87
74
88
## S3
75
89
76
- TODO.
90
+ For clouds with S3-compatible object storage (e.g. Ceph with [radosgw](https://docs.ceph.com/en/latest/radosgw/))
91
+ the S3 backend can be used. This approach uses a bucket per environment.
92
+
93
+ With the environment activated:
94
+
95
+ 1. Create a bucket:
96
+
97
+ ```shell
98
+ export TF_STATE_NAME="$(basename $APPLIANCES_ENVIRONMENT_ROOT)"
99
+ openstack container create $TF_STATE_NAME
100
+
101
+ 2. Create credentials:
102
+
103
+ ```shell
104
+ openstack ec2 credentials create
105
+ ```
106
+
107
+ From the returned values, set:
108
+
109
+ ```shell
110
+ export AWS_ACCESS_KEY_ID= # "access" value
111
+ export AWS_SECRET_ACCESS_KEY= # "secret" value
112
+ ```
113
+
114
+ Note these are available any time by running:
115
+
116
+ ```shell
117
+ openstack ec2 credentials list
118
+ ```
119
+
120
+ TODO: Think about automating these into the activate script??
121
+
122
+ 3. Create a backend file and commit it, for example:
123
+
124
+ ```terraform
125
+ # environments/$ENV/tofu/backend.tf:
126
+ terraform {
127
+ backend "s3" {
128
+ endpoint = "leafcloud.store"
129
+ bucket = "$ENV" # ** replace with environment name **
130
+ key = "environment.tfstate"
131
+ region = "dummy"
132
+
133
+ skip_region_validation = true
134
+ skip_credentials_validation = true
135
+ force_path_style = true
136
+ }
137
+ }
138
+ ```
139
+
140
+ Note that:
141
+ - `endpoint` is the radosgw address. If not known this can be determined by
142
+ creating a public bucket, and then getting the URL using
143
+ Project > Containers > (your public container) > Link, which provides an
144
+ URL of the form `https://$ENDPOINT/swift/...`.
145
+ `/swift`.
146
+ - `region` is required but not used in radosgw, hence `skip_region_validation`.
147
+ - `key` is an arbitrary state file name
148
+ - `skip_credentials_validation`: Disables STS - this may or may not be
149
+ required depending on the radosgw configuration.
150
+ - `force_path_style`: May or may not be required depending on the radosgw
151
+ configuration.
152
+
153
+ 4. Run:
154
+
155
+ ```shell
156
+ tofu init
157
+ ```
158
+
159
+ OpenTofu is now configured to use the cloud's S3 to store state for this
160
+ environment.
161
+
162
+
163
+ TODO: consider bucket versioning??
164
+ TODO: consider whether we should use a single bucket for both stg and prd to make
165
+ testing better??
166
+
167
+ TODO: understand -reconfigure vs -migrate-state?
0 commit comments