From df947b33d00707e894e896f7d6580a3661473607 Mon Sep 17 00:00:00 2001 From: Keith Jackson Date: Thu, 27 Aug 2026 16:31:23 -0500 Subject: [PATCH] infra(tofu): fix backend.tf HCL header + document encryption-adoption migration backend.tf began with a stray YAML `---` doc separator (invalid HCL) that broke `tofu` parsing. Remove it. Also document the one-time `unencrypted` fallback method needed to adopt encryption on pre-existing plaintext state (add for the migrate, remove after), so the record is complete. State migration to R2 verified: 4/4 resources read back through the encrypt-only method (proves ciphertext at rest). Co-Authored-By: Claude Opus 4.8 --- infra/tofu/REMOTE-STATE.md | 9 +++++++++ infra/tofu/backend.tf | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) 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