Terraform/OpenTofu

Terraform and OpenTofu: understand managed state, input/output, and versioned rollouts

Overview

Terraform and OpenTofu artifacts let you define, plan, and provision infrastructure resources declaratively using standard Terraform or OpenTofu configurations, while leveraging Bluebricks' orchestration engine for consistent, auditable execution across collections.

By encapsulating your IaC module as an artifact, you can integrate infrastructure changes directly into environment pipelines, apply collection-specific inputs, and ensure controlled, versioned rollouts.

Feature
Details

Dual-engine support

Select HashiCorp Terraform CLI or OpenTofu CLI per artifact

Automatic state backend

Bluebricks hosts and locks state (no S3 buckets or DynamoDB tables required)

Input auto-wiring

All props and secrets are passed in 0_bbx_props.auto.tfvars at runtime

Plan review

Plans show resource actions and "known after apply" outputs

Outputs capture

terraform output -json is parsed into artifact outputs after apply

Version pinning

The version field locks the CLI binary (defaults: Terraform 1.5.7, OpenTofu 1.8.7). See version pinning for limits and examples

State import

Optionally import an existing .tfstate file into managed state

For a complete guide to how inputs and outputs work across all IaC tools, see Inputs & Outputs.

Required files and directory structure

A Terraform/OpenTofu artifact requires standard .tf files in the directory specified by native.path:

my-terraform-artifact/
├── bricks.json             # Artifact manifest
└── iac/                    # native.path points here
    ├── main.tf             # Resource definitions
    ├── variables.tf        # Input variable declarations
    ├── outputs.tf          # Output declarations
    └── versions.tf         # Provider and Terraform version constraints

The native.path field in bricks.json must point to the directory containing your .tf files. Subdirectories, modules, and additional files (e.g., terraform.tfvars, .tfvars files) are supported.

bricks.json reference

Field
Required
Description

type

Yes

"terraform" or "opentofu" (alias "tofu")

path

Yes

Directory containing main.tf, modules, etc.

version

No

Locks the CLI binary for deterministic output

state

No

"managed" (default) = Bluebricks backend

state_path

No

Relative .tfstate file to import on first run

Version pinning

Pin a specific CLI version with the native.version field in bricks.json. Supported ranges:

Tool
Min version
Max version
Default

Terraform

1.0.0

1.5.7

1.5.7

OpenTofu

1.0.0

Latest

1.8.7

Terraform is capped at 1.5.7 because later versions use the BSL license. OpenTofu tracks the latest open-source release.

chevron-rightTerraform examplehashtag
chevron-rightOpenTofu examplehashtag

Verify your version configuration with a dry run:

Terraform vs OpenTofu

Feature
Terraform
OpenTofu

License

BSL 1.5.8+ (restricted)

MPL 2.0 (open source)

Latest supported

1.5.7

Latest

Syntax

Identical

Identical

Provider support

Full

Full

Terraform 1.5.7 and earlier use the MPL 2.0 license. Versions 1.5.8+ switched to the Business Source License (BSL), so Bluebricks caps Terraform at 1.5.7. OpenTofu is always MPL 2.0 with no restrictions.

Migrating from Terraform to OpenTofu: change native.type in your bricks.json from "terraform" to "opentofu". No code changes required since the syntax is identical.

How to create this artifact

The only requirement is a directory where you can run terraform plan (or tofu plan). If your root module works locally, Bluebricks can use it as-is. Bluebricks auto-discovers your variables and outputs, manages state, and wires everything into blueprints.

You can create a Terraform/OpenTofu artifact in two ways:

  • In the Bluebricks app during blueprint creation: select your repository and directory containing the root module, and Bluebricks generates the artifact automatically

  • Via CLI: run bricks blueprint publish from your root module directory. See Creating Artifacts for the full workflow, or Publish a Terraform Module for the detailed step-by-step CLI guide

The sections below explain how Bluebricks maps your code to inputs, outputs, and operations under the hood. Everything here is optional reading. To get started, head to Creating Blueprints.

Inputs

What becomes an input

Terraform/OpenTofu variable blocks are auto-discovered and mapped to props in bricks.json:

How inputs are delivered at runtime

Bluebricks writes all props and secrets to a single auto-vars file:

Runtime file
Contents

0_bbx_props.auto.tfvars

All props and secrets. Mark secret variables sensitive = true in HCL to keep them out of CLI output.

Secrets never appear in logs and Bluebricks wipes them from the runner after completion.

Outputs

What becomes an output

Terraform/OpenTofu output blocks are auto-discovered and mapped to outs in bricks.json:

How outputs are captured

After a successful apply, Bluebricks runs terraform output -json to capture all output values. During planning, output keys appear as "known after apply" placeholders.

Referencing outputs downstream

In a blueprint, reference a Terraform output from another package using Data.network_stack.vpc_id.

Supported operations

Operation
What it does

Plan

Initializes providers, generates a plan showing resource actions and placeholder outputs

Apply

Executes the plan, captures real outputs, and uploads the final state

Plan Destroy

Generates a plan showing everything that will be removed

Apply Destroy

Executes the destroy plan and deletes the remote state. The environment is marked Destroyed

Managed state

Bluebricks manages the Terraform backend automatically. State is locked during applies (only one apply at a time), encrypted at rest and in transit, and compared against live resources on every plan to surface drift in the UI. If state_path is set in bricks.json, the file is imported on the first apply and then removed.

Best practices

  • Mark secrets as sensitive = true in variables to suppress them in CLI output, logs, and state

  • Run terraform validate locally before pushing an artifact

  • Pin provider versions in required_providers to avoid unexpected upgrades

See also

Last updated

Was this helpful?