diff --git a/infra/tofu/REMOTE-STATE.md b/infra/tofu/REMOTE-STATE.md index 40905ac..e367201 100644 --- a/infra/tofu/REMOTE-STATE.md +++ b/infra/tofu/REMOTE-STATE.md @@ -38,6 +38,15 @@ tofu plan # MUST report "No chang If `plan` shows no changes, the migration is correct. If it wants to create/destroy nodes, STOP — the state did not carry over; re-check backend.hcl/creds and do not apply. +> **Adopting encryption on pre-existing *unencrypted* state (one-time — already done on first +> migration).** OpenTofu refuses to read a plaintext state while encryption is configured +> (`encountered unencrypted payload without unencrypted method configured`). For that ONE migration +> only, `TF_ENCRYPTION` must include a fallback so tofu can read plaintext and rewrite it encrypted: +> add `method "unencrypted" "migrate" {}` and give the `state` block a +> `fallback { method = method.unencrypted.migrate }`. Run the migrate, then **remove both** and +> `tofu init -reconfigure` so encryption is enforced. A fresh machine adopting the ALREADY-encrypted +> R2 state does NOT need this — the encrypt-only `.r2.env.example` is correct as-is. + ## Day-2 use (any machine) ```bash cd infra/tofu diff --git a/infra/tofu/backend.tf b/infra/tofu/backend.tf index c143648..3f85192 100644 --- a/infra/tofu/backend.tf +++ b/infra/tofu/backend.tf @@ -1,4 +1,3 @@ ---- # Remote state — Cloudflare R2 (S3-compatible), stored OFF the k3s cluster. # # WHY OFF-CLUSTER (the load-bearing decision): tofu state must live at or below the layer it