OpenTofu added native state encryption — what problem does it solve that Terraform never did, and how do you roll it out safely?
Quick Answer
State files contain secrets in plaintext (DB passwords, keys, tokens rendered into resource attributes); classic mitigations only encrypt at rest on the backend's side. OpenTofu's client-side state encryption encrypts the state and plans before they leave the process, with pluggable key providers (PBKDF2 passphrase, AWS KMS, GCP KMS...). Roll out with a key-migration-capable config: add encryption with a fallback block, apply to re-encrypt, and only then remove the fallback.
Detailed Answer
Why it matters: anyone who can read your backend (S3 bucket admins, backup operators, a leaked bucket credential) could read every secret your state ever captured — a classic audit finding with no first-class fix in Terraform (backend-side SSE still means the storage layer sees plaintext semantics and IAM on the bucket is the only wall). OpenTofu 1.7+ encrypts client-side: configure an encryption block with a key_provider and method, and state/plan files are ciphertext everywhere outside the running process. Rollout mechanics matter: (1) start with the fallback pattern — new encryption method as primary, unencrypted as fallback, so existing plaintext state can still be read; (2) run tofu apply (or state push after pull) to rewrite state encrypted; (3) remove the fallback so plaintext is refused thereafter; (4) key rotation reverses the pattern (new key primary, old key fallback). Operational cautions: losing the key means losing the state (treat key providers with backup discipline); every consumer — CI, developers, tooling that parses state — must have key access or break; and encrypted state kills quick debugging via 'cat terraform.tfstate', so invest in tofu state/show commands and break-glass procedures.
Code Example
terraform {
encryption {
key_provider "aws_kms" "main" {
kms_key_id = "arn:aws:kms:...:key/abc"
key_spec = "AES_256"
}
method "aes_gcm" "enc" { keys = key_provider.aws_kms.main }
state {
method = method.aes_gcm.enc
fallback {} # reads legacy plaintext during migration; remove after re-encrypt
}
}
}Interview Tip
Name the fallback-block migration dance and the 'lose the key, lose the state' consequence — those two operational details show you've thought past the feature announcement.