この記事の概要
2026年5月14日、OpenTofu 1.12.0がリリースされました。
最大のハイライトは、Terraform 0.7(2016年)から約10年間要望され続けながら放置されてきた「dynamic `prevent_destroy`」の実装です。
`lifecycle`ブロック内の`prevent_destroy`に変数を参照できるようになったことで、本番環境と開発環境でモジュールを分岐せずに安全性をコントロールできるようになりました。
加えてプロバイダーのチェックサム自動補完や`-json-into`オプションなど、現場の痒いところに手が届く改善が揃っています。
—
OpenTofu 1.12がもたらす3つの実務改善
OpenTofu 1.12.0の主な変更点は以下の3つです。
- `prevent_destroy`の動的化 — `lifecycle`ブロックで変数参照が可能に
- プロバイダーチェックサムの自動補完 — `tofu init`だけで`h1:`と`zh:`両形式のハッシュが揃う
- `-json-into=FILENAME`オプション — 人間向けターミナル出力とJSON出力の同時取得
順を追って詳しく見ていきましょう。
—
なぜ「static prevent_destroy」は現場の邪魔者だったのか
従来の痛み:環境ごとにモジュールをコピペするしかなかった
`prevent_destroy`は、IaCで管理しているリソースを誤って削除しないための安全弁です。
RDSインスタンスや重要なS3バケットに設定しておくことで、`tofu destroy`や意図しないリソース削除を防いでくれます。
# 以前はこう書くしかなかった(ハードコーディング)
resource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = true # 固定値しか書けない
}
}
問題は、`prevent_destroy = true`はモジュール内にハードコードされるため、開発環境でも同じ制約が適用されてしまうことでした。
開発環境では頻繁にリソースを作り直したいのに、`prevent_destroy`のせいでエラーが出ます。
かといって`false`にすれば本番が危険になります。
結果として多くのチームが取ってきた解決策は:
- 本番用モジュールと開発用モジュールを別々に管理(コピペ地獄)
- `prevent_destroy`を全部外して手順書で運用カバー(ヒューマンエラーの温床)
この問題はTerraform 0.7(2016年)のIssueとして報告されたが、HashiCorpは約10年間対応せず放置してきました。
OpenTofu 1.12でようやく解決しました。
—
実際に使ってみる:dynamic prevent_destroyの実装例
基本的な使い方
# variables.tf
variable "prevent_destroy_database" {
type = bool
description = "本番環境ではtrue、開発環境ではfalseを指定"
default = true
}
# main.tf
resource "aws_db_instance" "main" {
identifier = "myapp-db"
engine = "mysql"
engine_version = "8.4"
instance_class = "db.t3.medium"
allocated_storage = 20
lifecycle {
prevent_destroy = var.prevent_destroy_database # 変数参照OK!
}
}
# environments/prod/terraform.tfvars
prevent_destroy_database = true
# environments/dev/terraform.tfvars
prevent_destroy_database = false
これだけで、同一モジュールを本番と開発で使い回しながら、環境ごとに削除保護のオン/オフを切り替えられます。
モジュール呼び出し側からの制御
# 呼び出し側(ルートモジュール)
module "database" {
source = "./modules/database"
prevent_destroy_database = terraform.workspace == "production" ? true : false
}
`terraform.workspace`を使えば、ワークスペース名に応じて動的に切り替えることもできます。
制約事項に注意
現時点では「同一モジュール内の値」しか参照できません。
他モジュールの出力値や`data`ソースを直接参照することはまだできません。
複雑な依存関係が必要な場合はワークスペースや`tfvars`で渡す設計にしておきましょう。
—
`tofu init`のチェックサム問題が解消
地味に現場を悩ませてきたのが、`.terraform.lock.hcl`のチェックサム問題です。
# 以前のlock.hcl — zh: ハッシュしか入っていない
provider "registry.opentofu.org/hashicorp/aws" {
version = "5.90.0"
constraints = "~> 5.0"
hashes = [
"zh:abc123...",
# h1: ハッシュが不足しているためキャッシュ利用時にエラー
]
}
共有プロバイダーキャッシュやローカルミラーを使っているチームでは、`h1:`ハッシュが不足しているために`tofu init`が失敗するケースが多発していました。
回避策として`tofu providers lock -platform=linux_amd64 -platform=darwin_arm64`のような複数プラットフォーム向けコマンドを毎回手動実行する必要がありました。
OpenTofu 1.12以降は、`tofu init`が`zh:`と`h1:`両形式のハッシュを自動補完するようになりました。
# 初回 tofu init 実行後に自動的に両形式のハッシュが記録される
$ tofu init
# 生成されたlock.hcl
provider "registry.opentofu.org/hashicorp/aws" {
version = "5.90.0"
hashes = [
"h1:xyz789...", # 自動追加!
"zh:abc123...",
]
}
CI/CDパイプラインでキャッシュを活用しているチームにとっては、かなりの手間削減になります。
—
`-json-into`オプション:CI/CDとターミナル表示の両立
# ターミナルには人間向け出力、CIシステムにはJSON出力を同時送信
$ tofu plan -json-into=/tmp/plan_output.json
# ターミナルではいつも通りの見やすい差分表示
# /tmp/plan_output.json にはパース可能なJSON形式で同じ情報が保存される
Terraform/OpenTofuの出力をSlackに通知したり、独自のCI UIに統合したりするとき、`-json`フラグだと人間向け出力が消えてしまうのが悩みどころでした。
`-json-into`を使えば両方が取れます。
名前付きパイプ(`mkfifo`)経由でストリーム処理することも可能です。
—
Terraformから移行すべき今がその理由
OpenTofuはTerraformを「機能面で追い越した」
2023年8月のHashiCorp BSL移行以降、OpenTofuはLinux Foundation傘下でOSSとして開発を続けてきました。
2026年時点でのポイントは:
- dynamic prevent_destroy(OpenTofu 1.12)— Terraform未実装
- State暗号化(OpenTofu 1.7〜)— S3/GCS/Azure Blobのstateをクライアント側で暗号化
- プロバイダーとモジュールは後方互換 — 既存のTerraformコードがそのまま動く(大半のケース)
- BSL制約なし — 商用製品への組み込みや内部ツールへの利用が自由
移行コストは環境によって異なるが、`tofu`コマンドに置き換えるだけで動くケースが多くなっています。
# インストール(Homebrew)
brew install opentofu
# 既存のTerraformプロジェクトでそのまま実行
cd your-terraform-project
tofu init
tofu plan
移行の注意点
- Terraform Cloudはそのまま使えない — 代替はenv0、Spacelift、Scalr等
- provider `source`がOpenTofu Registryに変わる — `registry.terraform.io` → `registry.opentofu.org`(自動移行される)
- WinRMプロビジョナーが1.12で非推奨に — 1.13で削除予定、OpenSSH for Windowsへ移行が必要
—
まとめ
OpenTofu 1.12のキーポイントをまとめると:
- `prevent_destroy`に変数参照が使えるようになり、環境ごとのモジュールコピペが不要に
- `tofu init`がチェックサムを自動補完するため、CIでのlock.hcl管理が楽になる
- `-json-into`でターミナル出力とJSON出力の同時取得が可能に
10年越しの要望を実現したdynamic `prevent_destroy`は、IaCモジュールの設計を根本から改善する機能です。
Terraformをまだ使い続けているチームにとって、OpenTofu移行を検討する十分な理由になります。
まずは開発環境の1プロジェクトから試してみてください。
—


コメント