Files
home-network-k3s-impl/infra/tofu/.r2.env.example
T
jakman85andClaude Opus 4.8 485b9e3888 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]>
2026-08-27 15:57:12 -05:00

25 lines
858 B
Bash

# 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
}
'