infra(tofu): scaffold off-cluster R2 remote state (encrypted)
Local-only tfstate meant losing the workstation would strand a rebuild (apply would try to recreate the 3 live nodes). Move state to Cloudflare R2, which sits OUTSIDE the Proxmox->VM->cluster->Gitea chain, so a full cluster rebuild can still read it; encrypted at rest via OpenTofu native AES-GCM. Adds a partial s3 backend (R2 skip-flags), gitignored backend.hcl/.r2.env for the account-specific + secret bits, their .example templates, and a migration+DR runbook. Locking (use_lockfile) deferred to an OpenTofu >=1.10 bump (1.9.0 lacks it). Migration (tofu init -migrate-state) runs once the operator provisions the R2 bucket. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
91c82d2756
commit
485b9e3888
5 files changed
+139
No files matched your search
@@ -0,0 +1,24 @@
|
||||
# Copy to `.r2.env` (gitignored), fill in, then: source .r2.env
|
||||
# These are the ONLY secrets. They never enter git or tofu state.
|
||||
|
||||
# --- R2 S3 credentials (from Cloudflare R2 -> Manage API Tokens -> Object Read & Write) ---
|
||||
export AWS_ACCESS_KEY_ID="<R2_ACCESS_KEY_ID>"
|
||||
export AWS_SECRET_ACCESS_KEY="<R2_SECRET_ACCESS_KEY>"
|
||||
|
||||
# --- State-at-rest encryption (OpenTofu native, AES-GCM via PBKDF2 passphrase) ---
|
||||
# CRITICAL: store this passphrase in your PASSWORD MANAGER. It is required to read the state on any
|
||||
# machine and after any rebuild. It must be >= 16 characters (OpenTofu enforces a minimum).
|
||||
export TF_ENCRYPTION='
|
||||
key_provider "pbkdf2" "state" {
|
||||
passphrase = "<STRONG_PASSPHRASE_MIN_16_CHARS>"
|
||||
}
|
||||
method "aes_gcm" "state" {
|
||||
keys = key_provider.pbkdf2.state
|
||||
}
|
||||
state {
|
||||
method = method.aes_gcm.state
|
||||
}
|
||||
plan {
|
||||
method = method.aes_gcm.state
|
||||
}
|
||||
'
|
||||
Reference in new issue
Block a user