In this episode you run the OpenTofu core workflow: init, plan, apply, and destroy. We also cover the OpenTofu Registry where providers and modules are downloaded, as well as a drop-in replacement migration procedure from Terraform without changing a single line of HCL.

In episode 1 we covered the history: OpenTofu's birth from Terraform's license change, Linux Foundation support, and the commitment to 1:1 backward compatibility. That commitment isn't just a promise — in episode 2 you'll prove it directly by running the core OpenTofu workflow from start to finish.
Three things are covered: the core workflow (init → plan → apply → destroy), the OpenTofu Registry where providers and modules are downloaded, and a smooth migration procedure from Terraform. By the end of the episode, you can take an existing Terraform project and run it with tofu without changing anything.
The OpenTofu workflow follows a four-step cycle that is the universal language of IaC teams everywhere.
| Command | Purpose | Frequency |
|---|---|---|
tofu init | Downloads providers and modules and prepares the backend | Once per project, or when changes occur |
tofu plan | Computes a change preview without touching the cloud | Every time you're about to make changes |
tofu apply | Executes approved changes to the cloud | After the plan is approved |
tofu destroy | Removes all managed resources | When the environment is no longer needed |
tofu init is the front door. It reads the required_providers block, downloads providers from the registry, records versions in .terraform.lock.hcl, and prepares the backend where state is stored.
tofu init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.94.0...
- Installed hashicorp/aws v5.94.0 (signed by HashiCorp)
OpenTofu has been successfully initialized!tofu plan runs a dry run. It compares the actual state with the HCL code, then produces a plan of action. This is your main safety net — any mistakes here don't damage the cloud.
tofu plan
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
# aws_instance.web will be created
+ resource "aws_instance" "web" {
+ ami = "ami-0c55b159cbfafe1f0"
+ instance_type = "t3.micro"
}
Plan: 1 to add, 0 to change, 0 to destroy.Tip
Make a habit of running tofu plan before tofu apply every time — especially on teams. A plan can be saved with tofu plan -out=plan.tfplan so that apply only executes the already-approved plan rather than recomputing from the latest code.
tofu apply is the executor. It creates, modifies, or deletes cloud resources according to the plan. OpenTofu shows a summary and asks for confirmation before starting (which can be skipped with the -auto-approve flag).
aws_instance.web: Creating...
aws_instance.web: Still creating... [10s elapsed]
aws_instance.web: Creation complete after 17s
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.tofu destroy runs the reverse plan: deleting all resources recorded in state. This is crucial for test environments and cost control.
tofu destroyWhen tofu init looks for a provider or module, it shops at registry.opentofu.org. This registry is a public catalog of official providers (like hashicorp/aws) and reusable community modules. Unlike "everything has to be built from scratch," this registry is what makes IaC so productive.
Providers still come from hashicorp/aws — an address compatible with Terraform — so most of the ecosystem works right away. You'll see these provider declarations in detail in episode 3. Modules can also be pulled from the registry, Git, or a local path — for this episode, it's enough to know that the download location is controlled by the required_providers block and the source attribute on modules.
This is the part most engineers are looking for: how to move from Terraform to OpenTofu without replacing a single line of HCL. Because OpenTofu is built from a fork of Terraform 1.5.x and maintains 1:1 compatibility, the procedure is very simple.
Step 1: replace the binary. Make sure tofu is installed and replace calls to terraform.
Step 2: run the usual workflow. tofu init, tofu plan, tofu apply read the exact same HCL and state.
Step 3: for remote backends, tofu init -migrate-state copies state to the same backend without data loss.
tofu init -migrate-stateA fact that often surprises people: OpenTofu can read the .terraform.lock.hcl produced by Terraform, so you don't need to delete or regenerate lock files.
Many scripts still call terraform. For a smooth transition, use an alias:
alias terraform=tofu
terraform --version # actually executes OpenTofuAdd this alias line to ~/.bashrc or ~/.zshrc to make it permanent. For repos with many CI scripts, this makes the transition "silent" — nothing changes from the script's point of view.
Warning
A few things need attention during migration: scripts that call literal terraform in CI (replace with tofu or an alias), and the proprietary Terraform Cloud backend — for that, consider another backend such as S3, covered in episode 5.
Summary of episode 2:
tofu init → tofu plan → tofu apply → tofu destroy.hashicorp/aws remaining compatible.terraform=tofu alias makes the transition transparent for legacy scripts.You can now run OpenTofu end-to-end. In the next episode, episode 3, we dive deeper into the configuration language: provider, resource, and data source declarations — the HCL foundation you'll use in almost every .tf file. See you there!