State & plan encryption

The headline OpenTofu-only feature.

Advanced14 min · lesson 9 of 12

This is the headline reason to choose OpenTofu on its own merits: native client-side state and plan encryption. Terraform state can contain secrets in plaintext — database passwords, private keys, tokens — so anyone who reads the state file or a stored plan reads the secrets. OpenTofu can encrypt the state and plan files with a key you control, before they are written anywhere, so the backend only ever stores ciphertext.

You configure it in an encryption block under terraform {}, choosing a key provider (a static key, PBKDF2 from a passphrase, or a cloud KMS — AWS KMS, GCP KMS) and a method (AES-GCM). Once enabled, tofu encrypts state on write and decrypts on read transparently; the file at rest, in the backend or in a plan artifact, is unreadable without the key.

encryption.tofu
terraform {
encryption {
key_provider "aws_kms" "prod" {
kms_key_id = "arn:aws:kms:us-east-1:...:key/abcd-1234"
region = "us-east-1"
key_spec = "AES_256"
}
method "aes_gcm" "prod" { keys = key_provider.aws_kms.prod }
state { method = method.aes_gcm.prod } # encrypt state
plan { method = method.aes_gcm.prod } # and saved plans
}
}

Why this matters

It closes the single most common IaC data-exposure path. With backend-only (server-side) encryption, anyone with read access to the bucket gets plaintext via the API; with client-side encryption, the state is ciphertext everywhere except in memory during a run, so a leaked backend, a stolen plan artifact from CI, or an over-broad bucket policy no longer hands over your secrets. Rotation is supported by listing multiple keys (new one first to encrypt, old ones still able to decrypt).

terminal
$ tofu apply # state is written encrypted
$ aws s3 cp s3://acme-tofu-state/prod/network.tfstate - | head -c 60
{"encrypted_data":"k9Fw2... # ciphertext at rest, not readable JSON
Lose the key, lose the state
Client-side encryption means the key is now critical: if the KMS key is deleted or the passphrase is lost, the state is unrecoverable. Use a managed KMS with proper key policies and backups rather than a static key in a repo, plan key rotation before you need it, and make sure every place that runs tofu (every CI runner, every engineer) can reach the key.