65 lines
2.4 KiB
Terraform
65 lines
2.4 KiB
Terraform
terraform {
|
|
required_version = ">= 1.7.0" # state encryption (below) requires >= 1.7.0
|
|
|
|
required_providers {
|
|
hcloud = {
|
|
source = "hetznercloud/hcloud"
|
|
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. Backend blocks can't reference variables, so
|
|
# this is all non-secret - credentials come from 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
|
|
# before invoking tofu (same bucket, same credentials).
|
|
backend "s3" {
|
|
bucket = "luke-else"
|
|
key = "tofu/terraform.tfstate"
|
|
|
|
# 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 the bucket's actual location.
|
|
region = "eu-central"
|
|
|
|
endpoints = {
|
|
s3 = "https://nbg1.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
|
|
}
|
|
|
|
# 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.
|
|
provider "hcloud" {}
|