Introduced in OpenTofu 1.7.0 is the ability to encrypt the state file. Here is how to use it.
If you used tls_private_key to generate private key, you know that the key is stored in terraform state file in plaintext. With state encryption, you can now encrypt the state file and secure such sensitive data.
In prior versions, if I use this to generate a key
resource tls_private_key this {
algorithm = "ED25519"
}
I can see the key in my terraform state file:
❯ cat terraform.tfstate
{
"version": 4,
"terraform_version": "1.7.0",
"serial": 1,
"lineage": "97da73b2-7b36-8c05-7118-b8f79ee412c2",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "tls_private_key",
"name": "this",
"provider": "provider[\"registry.opentofu.org/hashicorp/tls\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"algorithm": "ED25519",
"ecdsa_curve": "P224",
"id": "dabe1b64ee4e20d42eb3eabbfdd83c581681e1f0",
"private_key_openssh": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz\nc2gtZWQyNTUxOQAAACAr02fbVVS5ypxQmhl+Ni66RG+EetbdEhpzEg2aXXzUEAAA\nAIiUxeFClMXhQgAAAAtzc2gtZWQyNTUxOQAAACAr02fbVVS5ypxQmhl+Ni66RG+E\netbdEhpzEg2aXXzUEAAAAEDDwh6y7aIDB1H7TTMiY5mU+hXHDcoOs+aWC0HxuVA4\nmivTZ9tVVLnKnFCaGX42LrpEb4R61t0SGnMSDZpdfNQQAAAAAAECAwQF\n-----END OPENSSH PRIVATE KEY-----\n",
"private_key_pem": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIMPCHrLtogMHUftNMyJjmZT6FccNyg6z5pYLQfG5UDia\n-----END PRIVATE KEY-----\n",
"private_key_pem_pkcs8": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIMPCHrLtogMHUftNMyJjmZT6FccNyg6z5pYLQfG5UDia\n-----END PRIVATE KEY-----\n",
"public_key_fingerprint_md5": "e6:55:7d:50:2f:cf:8c:30:c9:69:1e:95:aa:ac:68:89",
"public_key_fingerprint_sha256": "SHA256:Ro7frtlxZ7D6PZaX4APHjH0TbfIpPF1Y/sLhiDlLJxw",
"public_key_openssh": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICvTZ9tVVLnKnFCaGX42LrpEb4R61t0SGnMSDZpdfNQQ\n",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAK9Nn21VUucqcUJoZfjYuukRvhHrW3RIacxINml181BA=\n-----END PUBLIC KEY-----\n",
"rsa_bits": 2048
},
"sensitive_attributes": []
}
]
}
],
"check_results": null
}
With opentofu, I’ll need to add an encryption block to the terraform block.
terraform {
encryption {
key_provider pbkdf2 key1 {
passphrase = "1234567890123456"
}
method "unencrypted" "migrate" {}
method aes_gcm method1 {
keys = key_provider.pbkdf2.key1
}
state {
method = method.aes_gcm.method1
fallback {
method = method.unencrypted.migrate
}
}
}
}
resource tls_private_key this {
algorithm = "ED25519"
}
After terraform apply, examine the state file and I can see it has been encrypted:
❯ cat terraform.tfstate
{"serial":1,"lineage":"21803b8a-87bb-1af0-cac1-5e7c2355178c","meta":{"key_provider.pbkdf2.key1":"eyJzYWx0IjoicDdzQXdXTGN5Yzc4UjFqMW13TjRReHpXOWVuK1BJQ1dDbHpnNkwvdzRHaz0iLCJpdGVyYXRpb25zIjo2MDAwMDAsImhhc2hfZnVuY3Rpb24iOiJzaGE1MTIiLCJrZXlfbGVuZ3RoIjozMn0="},"encrypted_data":"otjx3pMLbDGe46vy+rKjytrjlYYxbJKXECpURSOTx1T1Uy11fe4YIMDXojtcSIQwkjQ5/uLtSqEJeVMVXoIHRwm1shPcXBmzOuuAQYouR4IvR/7IsZb...
RsUtIcDqCJfP5HDjTfIzj0K7ojwrf/NId5vK8tDWTXwNBg829z8Ss8l4UW1Ox6CoN/tv/dg/Ya2DdPiXpkKHPw3+yRh7qy3AlHj72+XakNSbk6qQUH+yV40IIM4KOEsAcMBoX2Yukwov+THz/RtgwvrGf8Xj3qyK9FsPOyVWGv8=","encryption_version":"v0"}.
I wish the implementation can be simpler and can be generically used in not just the state file but any other data files. At times, I’m asked to import SSL certificate into ACM. The private key file is sensitive and there should be a way to encrypt it.
For more on state and plan encryption, see OpenTofu’s documentation.
![]()