Skip to content

OpenTofu

Reach has a full OpenTofu workspace that covers the entire IaC workflow. You can manage projects, configure providers and resources through a visual UI, run plan/apply/destroy with streaming output, inspect and modify state, visualize dependency graphs, manage workspaces, and generate HCL files — all without touching the command line.

Open the OpenTofu tab from the sidebar. If no OpenTofu is available, Reach shows a setup screen with an Install button.

Reach manages OpenTofu itself, the same way on Windows, macOS and Linux: it downloads the release for your platform from GitHub, verifies it against the SHA256SUMS the OpenTofu project publishes, and keeps it under Reach’s own tools directory, one folder per version. Nothing is written to your PATH and nothing needs a restart. A checksum mismatch installs nothing.

If a tofu (or terraform) is already on your PATH, Reach will use it until you install a managed version.

Every project runs the version it asks for, and the Actions tab says which: OpenTofu 1.11.4 · managed by Reach, or · system PATH.

  • A .opentofu-version file in the project directory pins it exactly — the same convention tenv uses, so the file works outside Reach too.
  • An exact required_version = "1.9.0" in the HCL counts as a pin. A range such as >= 1.6 is a constraint, not a choice, and does not.
  • Without a pin, the newest managed version runs.

The select beside the version chip changes the pin: pick a managed version, Use system PATH, or Install latest…. Installing writes the pin, so the choice sticks. A project that pins a version Reach has not downloaded yet gets it downloaded, verified and used on its next run, in the open — the run output says so.

Everything is organized around projects. A project maps to a directory on disk containing your .tf files. Project metadata (name, description, provider configs, variables, resources, outputs, backend, modules, locals, data sources, environments) is stored encrypted in the Reach vault.

Two ways to create a project:

New Project — Click the button, fill in:

  • Project Name — whatever you want to call it
  • Project Path — click Browse to pick a directory, or type manually
  • Description — optional

Reach creates the directory if needed and scaffolds a starter main.tf.

From Template — Click “From Template” to pick from a list of pre-built project templates (e.g., AWS EC2, Docker, Kubernetes). The template pre-populates providers, variables, and resources so you don’t start from scratch.

Cards show project name, path, description, and last-opened timestamp. Click to open. Trash icon to delete (with confirmation dialog). Deleting removes vault metadata but doesn’t touch files on disk.

Opening a project gives you a two-panel layout.

Lists all files in the project directory. Click a file to view its contents in the right panel with syntax highlighting. The panel collapses with the chevron button. Back to Projects at the bottom returns to the project list.

TabWhat it holds
OverviewThe run. A run bar says which environment and var file, whether state is encrypted, which backend, and on which machine; Validate and Plan sit beside it, and holds Init, Test, Format, Apply and the Auto-approve toggle. The result fills the rest: change summary, planned changes, live apply progress, diagnostics with file and line, outputs, raw log one click away.
CodeThe HCL builders as sections: Providers, Variables, Resources, Data Sources, Locals, Modules, Outputs, Environments. Generate HCL previews every .tf file Reach would write.
StateState (inspect, move, remove, import), Graph, Workspaces, Backend and encryption. At the foot of State is the danger zone: Destroy, enabled only after you type the project’s name.

The version chip on the right of the tab bar says which OpenTofu runs the project and lets you change it.

Plan is the action. When a plan reports changes, a gate appears above the result: This is the plan that will be applied. Nothing else. Apply this plan applies the saved plan file — exactly what you reviewed, no second plan — and Discard deletes it. Full plan opens the attribute-level view. Apply from the menu without a saved plan tells you to plan first unless Auto-approve is on.

Every run shows in Overview, whichever tab started it: state operations and imports from the State tab included.

The select on the run bar lists Local and every open SSH session. Pick a session to run OpenTofu on that host; the list refreshes when you open it.

The Providers tab manages infrastructure providers (AWS, Azure, GCP, Docker, Kubernetes, etc.).

Click Add Provider to open the provider picker. It shows a catalog of available providers. Select one, give it a name, and it’s added to your project.

Click Configure on any provider card to open a configuration modal. The form fields are driven by the provider’s schema — for example, AWS shows fields for region, access_key, secret_key, etc. Field types include text, numbers, booleans, dropdowns, and password fields for sensitive values.

Click Fetch Schema to download the provider’s resource schema from the registry. This enables Reach to show you available resource types and their configuration fields when adding resources. A badge shows how many resource types are available after fetching.

Click Remove on the provider card. The provider configuration is removed from the project.

The Variables tab defines input variables for your project.

Each variable shows: name, type, default value, sensitive flag, description, and edit/delete buttons. Sensitive variables show their default value masked.

Click Add Variable or the edit button on an existing one. The editor modal has:

  • Name — variable name (must be unique)
  • Type — dropdown: string, number, bool, list, map
  • Default — optional default value
  • Sensitive — checkbox to mark the variable as sensitive
  • Description — optional description

The Resources tab manages infrastructure resources.

Click Add Resource to open the resource picker. If you’ve fetched a provider schema, the picker shows all available resource types for that provider (e.g., aws_instance, aws_s3_bucket). Select one and give it a logical name.

Click Configure on a resource card. The configuration modal shows schema-driven fields specific to that resource type. For example, an aws_instance might show fields for ami, instance_type, tags, etc. Required fields are marked. Help text is shown where available.

Click Remove on the card.

Data sources let you read information from external sources (existing infrastructure, APIs, etc.).

Click Add Data Source to open a picker with:

  • Search — filter by name, type, or description
  • Category pills — All, Compute, Network, Storage, Container, Utility
  • Grid of available data sources

Select one, name it, and configure it through the schema-driven form.

Environments let you maintain different sets of variable values for different deployments (dev, staging, production).

  • Dropdown to select an existing environment (active one marked with *)
  • Delete button to remove an environment
  • New environment input + Add button to create one

When an environment is selected, you see a form with one row per variable:

  • Variable name and description
  • Input field (password field if the variable is sensitive)
  • Placeholder shows the variable’s default value

Click Save Values to persist. Click Set Active to make this environment the one used by commands.

The Backend tab configures where OpenTofu stores state.

Dropdown with available backend types from the catalog (local, s3, azurerm, gcs, consul, http, etc.). Each shows a description.

After selecting a type, a form appears with schema-driven fields specific to that backend. For example, S3 shows bucket, key, region, encrypt, etc. Sensitive fields use password inputs.

If a backend is already configured, it shows the type and field values (sensitive ones masked). A Remove button clears it.

Locals define computed values that can reference variables and other resources.

Click Add Local. The form has:

  • Name — must start with a letter or underscore, alphanumeric characters only. Duplicate names are rejected.
  • Expression — HCL expression (e.g., "${var.prefix}-${var.environment}")

Each local card shows its name and expression. Edit and Delete buttons on each.

Modules reference reusable OpenTofu configurations.

Click Add Module. The form has:

  • Name — required, validated
  • Source — module source (local path like ./modules/vpc, Git URL, or registry reference)
  • Version — optional version constraint (e.g., ~> 1.0)
  • Inputs — dynamic key-value pairs. Click Add Input to add rows with key and value fields. Remove button per row.

Each module card shows name, source, and version. Edit and Remove buttons.

The State tab lets you inspect and modify the OpenTofu state file.

Shows all resources currently tracked in state. Click Refresh to reload.

  • Show — runs tofu state show <address> and displays the result in the output panel
  • Move — opens an input for the new address. Confirm to run tofu state mv <old> <new>. Useful for renaming resources.
  • Remove — confirmation dialog, then runs tofu state rm <address>. Removes the resource from state without destroying it.

Click Import Resource to open a modal with:

  • Address — the resource address to import into (e.g., aws_instance.web)
  • ID — the real-world resource ID (e.g., i-1234567890abcdef0)

Runs tofu import <address> <id> to bring an existing resource under management.

The Graph tab visualizes the dependency relationships between your resources.

  • Pan — click and drag to move around
  • Zoom — mouse wheel (0.3x to 3x scale)
  • Nodes — colored rectangles representing resources. Colors vary by provider: AWS in amber, Azure in blue, Google in red, Docker in cyan, Kubernetes in blue.
  • Edges — lines with arrows showing which resources depend on which

Click Refresh to regenerate the graph from the current configuration.

The Outputs tab has two sections.

Define what values should be exported from your configuration.

Click Add Output. The editor has:

  • Name — unique output name
  • Value — HCL expression (e.g., aws_instance.web.public_ip)
  • Description — optional
  • Sensitive — checkbox to mask the value in logs

Edit and Delete buttons on each defined output.

Click Refresh to fetch actual output values from the current state. Each value shows:

  • Name
  • Type badge (string, number, etc.)
  • Actual value (or [sensitive] if marked sensitive)

This is the equivalent of running tofu output on the command line.

Workspaces let you manage multiple isolated state environments within the same configuration.

Highlighted box showing which workspace is active.

Each workspace shows its name, a Select button to switch to it, and a Delete button (disabled for the default workspace — you can’t delete it).

Input field + Create button at the bottom. Creates the workspace with tofu workspace new <name> and switches to it.

The Generate HCL button in the tab bar opens a preview showing all the .tf files that Reach would generate from your current project configuration (providers, variables, resources, outputs, backend, locals, modules, data sources). You can review the generated code and write it to disk.

This is the bridge between the visual UI and actual HCL files. You can configure everything through the UI panels and then generate the corresponding Terraform-compatible code.

All project metadata — providers, variables, resources, outputs, backend config, environments, locals, modules, data sources — is stored encrypted in the Reach vault. The actual .tf files and state live on disk in your project directory.

Sensitive values like provider credentials, backend access keys, and sensitive variable defaults are encrypted at rest in the vault. The state file itself is managed by OpenTofu and should be secured through its own mechanisms (remote backends with encryption, etc.).

Projects persist across app restarts. When you reopen Reach, your project list and all configuration is loaded from the vault.

Every command runs non-interactively (-input=false, TF_IN_AUTOMATION=1, TF_INPUT=0) — nothing can stop and wait for a prompt you cannot see.

plan, apply and destroy run with -json, OpenTofu’s machine-readable UI. Reach folds the stream into a run view: the change summary as the header (+3 ~1 −1), the planned changes as a list, apply progress as rows that move from running to done with the resource id and elapsed time, diagnostics as cards with the file and line, and outputs as a table. Commands that only speak prose — init, validate, fmt — show their output as text, and Raw log switches any run back to the text OpenTofu wrote.

plan runs with -detailed-exitcode: exit 0 means no changes, 2 means there are changes to apply, and the verdict chip says which. Only 1 is an error.

apply without Auto-approve applies the plan the last plan saved — exactly what you reviewed, no second plan, no prompt — because the saved plan is the approval. With no saved plan and no Auto-approve, Reach says so instead of starting a run that would stop to ask. destroy always needs Auto-approve.

The same arguments are used when a project runs on a remote host over SSH.

OpenTofu (1.7+) can encrypt the state file and saved plans; Terraform cannot read the result. Under Backend → State encryption, turn it on and set a passphrase (or generate one). Reach writes an encryption block into the generated HCL — AES-256-GCM under a PBKDF2 key, enforced so an unencrypted state is refused rather than written — with the passphrase as var.reach_state_passphrase, declared sensitive. The passphrase itself stays in Reach’s vault with the project and reaches OpenTofu as TF_VAR_reach_state_passphrase in the run’s environment, so the HCL can be committed and the secret never can. On a remote run it rides on the command line, single-quoted, and is briefly visible in that host’s process list.

Lose the passphrase and the state cannot be read by anyone, Reach included. Keep a copy somewhere you trust.