feat: Added remote state storage in S3 bucket
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Copy to backend.hcl and fill in - backend.hcl itself is gitignored, never
|
||||
# commit real values there. Used as `tofu init -backend-config=backend.hcl`
|
||||
# (control.sh's OpenTofu > init does this for you).
|
||||
#
|
||||
# This is the *same* S3-compatible bucket already used for service backups
|
||||
# (BACKUP_S3_BUCKET/BACKUP_S3_ENDPOINT in control.sh > Set variables) - just a
|
||||
# different object key so state never collides with backup archives.
|
||||
# Credentials are NOT set here: the s3 backend picks up the standard
|
||||
# AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY environment variables, which
|
||||
# control.sh exports from BACKUP_S3_ACCESS_KEY_ID/BACKUP_S3_SECRET_ACCESS_KEY
|
||||
# for you.
|
||||
|
||||
bucket = "your-hetzner-bucket-name" # same bucket as BACKUP_S3_BUCKET
|
||||
key = "tofu/terraform.tfstate" # path *within* the bucket - keep this distinct from the backup/ prefix
|
||||
|
||||
# Hetzner Object Storage doesn't have "AWS regions" - this just has to be a
|
||||
# syntactically valid region string, it isn't used to route the request (the
|
||||
# endpoint below does that). Match it to your bucket's actual location.
|
||||
region = "eu-central"
|
||||
|
||||
endpoints = {
|
||||
# e.g. https://nbg1.your-objectstorage.com - same value as BACKUP_S3_ENDPOINT
|
||||
s3 = "https://your-location.your-objectstorage.com"
|
||||
}
|
||||
|
||||
# Hetzner Object Storage isn't AWS: skip the AWS-specific validation/lookup
|
||||
# calls the backend would otherwise make, and address the bucket path-style
|
||||
# (https://endpoint/bucket) rather than AWS's virtual-hosted style.
|
||||
use_path_style = true
|
||||
skip_credentials_validation = true
|
||||
skip_region_validation = true
|
||||
skip_requesting_account_id = true
|
||||
skip_s3_checksum = true
|
||||
skip_metadata_api_check = true
|
||||
@@ -74,3 +74,9 @@ variable "dns_zones" {
|
||||
type = list(string)
|
||||
default = ["luke-else.co.uk"]
|
||||
}
|
||||
|
||||
variable "state_encryption_passphrase" {
|
||||
description = "Passphrase (min 16 chars) used to encrypt the OpenTofu state file client-side before it's written to the S3 backend - see versions.tf. Set via the TF_VAR_state_encryption_passphrase environment variable (control.sh > Set variables), never as a literal default here."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
+30
-1
@@ -1,5 +1,5 @@
|
||||
terraform {
|
||||
required_version = ">= 1.6.0"
|
||||
required_version = ">= 1.7.0" # state encryption (below) requires >= 1.7.0
|
||||
|
||||
required_providers {
|
||||
hcloud = {
|
||||
@@ -7,6 +7,35 @@ terraform {
|
||||
version = "~> 1.54" # hcloud_zone / hcloud_zone_rrset (DNS) require >= 1.54.0
|
||||
}
|
||||
}
|
||||
|
||||
# State lives in the same Hetzner Object Storage bucket used for service
|
||||
# backups (see readme.md > Persistent data), under its own key so it never
|
||||
# collides with backup objects. Deliberately empty (partial configuration):
|
||||
# backend blocks can't reference variables, so bucket/key/endpoint are
|
||||
# supplied at `tofu init` time via -backend-config=backend.hcl (gitignored,
|
||||
# see backend.hcl.example) and credentials via the standard
|
||||
# AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY environment variables - control.sh
|
||||
# exports both from the BACKUP_S3_* variables before invoking tofu.
|
||||
backend "s3" {}
|
||||
|
||||
# State is encrypted client-side, independent of anything the bucket does -
|
||||
# Hetzner Object Storage only supports SSE-C (a per-request customer key),
|
||||
# not the SSE-S3 header the s3 backend's own `encrypt` option sends, so that
|
||||
# option silently no-ops against Hetzner. `enforced` refuses to ever read or
|
||||
# write unencrypted state, so a missing passphrase fails loudly instead of
|
||||
# falling back to plaintext.
|
||||
encryption {
|
||||
key_provider "pbkdf2" "state" {
|
||||
passphrase = var.state_encryption_passphrase
|
||||
}
|
||||
method "aes_gcm" "state" {
|
||||
keys = key_provider.pbkdf2.state
|
||||
}
|
||||
state {
|
||||
method = method.aes_gcm.state
|
||||
enforced = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Reads the token from the HCLOUD_TOKEN environment variable.
|
||||
|
||||
Reference in New Issue
Block a user