---
name: opentofu-iac
description: "OpenTofu/HCL authoring, drop-in Terraform migration, client-side state encryption, and tofu-only features. Author and operate OpenTofu: drop-in migration from Terraform (tofu init, state and provider lockfile reuse, CI swaps), client-side state encryption with PBKDF2/AWS-KMS/GCP-KMS key providers, and OpenTofu-only features like early variable evaluation in backend/module source, provider-defined functions, and for_each on import and removed blocks. Covers .tofu/.tf precedence, registry.opentofu.org providers, and state backend config."
license: MIT
---

# OpenTofu Migrator

OpenTofu Migrator helps you move existing Terraform configurations to OpenTofu and then take advantage of the features that only exist in the fork. It covers the in-place migration path, client-side state encryption, and OpenTofu-specific HCL constructs that the upstream Terraform CLI rejects. It is aimed at platform and DevOps engineers who already run `terraform` in CI and want a low-risk switch without rewriting modules.

## When to use it

- You want to swap `terraform` for `tofu` in CI/CD and need the state, provider lockfile, and `.tf` files to keep working untouched.
- You need state encrypted at rest with a key you control, not just relying on backend bucket encryption.
- You want OpenTofu-only language features such as variables/locals evaluated early enough to parameterize a `backend` block or a module `source`.
- You are writing provider-defined functions and want them resolved by `tofu`.

## How it works

Migration is intentionally boring: `tofu init` reads your existing `.terraform.lock.hcl` and remote state as-is, so a project usually moves over by replacing the binary. The skill helps with the CI swap (changing `terraform` invocations to `tofu`), checking provider compatibility in the lockfile, and the `tofu plan`/`tofu apply` sanity loop after switching.

For encryption it authors an `encryption` block under `terraform {}`, wiring a `key_provider` (`pbkdf2` with a passphrase, `aws_kms`, or `gcp_kms`) to a `method "aes_gcm"` and attaching it to `state` and `plan`. It supports the `unencrypted` fallback used during rollout and key rotation via a second method.

It also authors tofu-only constructs: early variable evaluation in `backend` and module `source`, and `provider::` namespaced function calls.

## Usage

```bash
curl -fsSL --create-dirs -o ~/.claude/skills/opentofu-iac/SKILL.md https://claudeskil.com/skills/opentofu-iac/SKILL.md

tofu init      # reuses .terraform.lock.hcl + existing state
tofu plan      # expect a no-op diff right after migrating
```

```hcl
terraform {
  encryption {
    key_provider "pbkdf2" "k" {
      passphrase = var.state_passphrase
    }
    method "aes_gcm" "m" {
      keys = key_provider.pbkdf2.k
    }
    state { method = method.aes_gcm.m }
    plan  { method = method.aes_gcm.m }
  }
}
```

## Tips & gotchas

- Set `TF_ENCRYPTION` (or the `encryption` block) consistently across every machine and CI runner — once state is encrypted, a runner without the key cannot read it.
- To roll encryption out gradually, add an `unencrypted {}` fallback so `tofu` can read old plaintext state, then remove it after the first encrypted apply.
- The PBKDF2 passphrase must be at least 16 characters; shorter ones fail at init.
- Encrypted state is opaque to tools that parse `terraform.tfstate` directly — decrypt via `tofu` first.

## FAQ

**Can I migrate back to Terraform later?** Only if you avoided tofu-only features and left state unencrypted; encrypted state and `provider::` functions are not readable by the Terraform CLI.

**Does my provider lockfile still work?** Yes — `tofu init` consumes the existing `.terraform.lock.hcl` and matching provider hashes.

**Is key rotation supported?** Yes, by defining a second `method` and listing both keys so old state decrypts while new writes use the new key.
